@thanh01.pmt/curriculum-kit 1.0.5 → 1.0.7

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
@@ -4,7 +4,7 @@ import { z } from 'zod';
4
4
  import { createGoogleGenerativeAI } from '@ai-sdk/google';
5
5
  import { createOpenAI } from '@ai-sdk/openai';
6
6
  import { createDeepSeek } from '@ai-sdk/deepseek';
7
- import { generateObject, streamObject } from 'ai';
7
+ import { generateObject, streamObject, streamText } from 'ai';
8
8
  import pLimit from 'p-limit';
9
9
  import fsPromises from 'fs/promises';
10
10
  import crypto, { createHash } from 'crypto';
@@ -12,8 +12,7 @@ import { createClient } from '@supabase/supabase-js';
12
12
  import { fileURLToPath } from 'url';
13
13
  import { jsonrepair } from 'jsonrepair';
14
14
  import { Octokit } from '@octokit/rest';
15
- import * as workflowPkg from 'workflow';
16
- import { getStepMetadata, RetryableError, sleep } from 'workflow';
15
+ import { defineHook, getStepMetadata, RetryableError, sleep } from 'workflow';
17
16
 
18
17
  var __defProp = Object.defineProperty;
19
18
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -4232,9 +4231,9 @@ _Unit: {{UNIT_ID}} | Module: {{MODULE_ID}} | Format: Mermaid Diagrams + Printabl
4232
4231
  var SLIDE_LAYOUT_PRESETS = [
4233
4232
  {
4234
4233
  id: "title-hero",
4235
- name: "B\xECa & Gi\u1EDBi thi\u1EC7u (Title Cover)",
4234
+ name: "Title & Speaker Cover",
4236
4235
  category: "cover",
4237
- description: "Slide b\xECa m\u1EDF \u0111\u1EA7u \u1EA5n t\u01B0\u1EE3ng v\u1EDBi ti\xEAu \u0111\u1EC1 l\u1EDBn, ph\u1EE5 \u0111\u1EC1 v\xE0 th\xF4ng tin gi\u1EA3ng vi\xEAn.",
4236
+ description: "High-impact opening slide with large title, subtitle, and speaker credentials.",
4238
4237
  layout: {
4239
4238
  boxes: [
4240
4239
  {
@@ -4279,22 +4278,22 @@ var SLIDE_LAYOUT_PRESETS = [
4279
4278
  textAlign: center
4280
4279
  -->
4281
4280
 
4282
- # \u{1F680} Ti\xEAu \u0110\u1EC1 B\xE0i Gi\u1EA3ng Ch\xEDnh
4283
- ### Ph\u1EE5 \u0111\u1EC1 ng\u1EAFn g\u1ECDn, truy\u1EC1n c\u1EA3m h\u1EE9ng v\xE0 \u0111\u1ECBnh v\u1ECB m\u1EE5c ti\xEAu
4281
+ # \u{1F680} Engineering Scalable Cloud Systems
4282
+ ### Principles, Bottlenecks, and Real-World Architecture Patterns
4284
4283
 
4285
- **Gi\u1EA3ng vi\xEAn:** Th\u1EA7y Nguy\u1EC5n V\u0103n A | **Th\u1EDDi l\u01B0\u1EE3ng:** 45 ph\xFAt | **C\u1EA5p \u0111\u1ED9:** Trung c\u1EA5p
4284
+ **Presenter:** Senior Systems Architect | **Duration:** 45 mins | **Level:** Intermediate
4286
4285
 
4287
4286
  <!--
4288
4287
  Presenter Notes:
4289
- - Ch\xE0o m\u1EEBng h\u1ECDc vi\xEAn, gi\u1EDBi thi\u1EC7u m\u1EE5c ti\xEAu b\xE0i h\u1ECDc h\xF4m nay.
4290
- - Kh\u01A1i g\u1EE3i s\u1EF1 t\xF2 m\xF2 b\u1EB1ng c\xE2u h\u1ECFi m\u1EDF \u0111\u1EA7u v\u1EC1 b\xE0i to\xE1n th\u1EF1c t\u1EBF.
4288
+ - Welcome the audience and outline today's primary engineering goals.
4289
+ - Spark curiosity with an opening hook about scaling under high concurrency.
4291
4290
  -->`
4292
4291
  },
4293
4292
  {
4294
4293
  id: "two-column-split",
4295
- name: "So S\xE1nh 2 C\u1ED9t (2-Column Comparison)",
4294
+ name: "Two-Column Comparison",
4296
4295
  category: "split",
4297
- description: "B\u1ED1 c\u1EE5c chia \u0111\xF4i m\xE0n h\xECnh \u0111\u1EC3 so s\xE1nh ph\u01B0\u01A1ng ph\xE1p c\u0169 vs m\u1EDBi, l\xFD thuy\u1EBFt vs th\u1EF1c t\u1EBF.",
4296
+ description: "Balanced side-by-side comparison for legacy vs modern patterns or pros vs cons.",
4298
4297
  layout: {
4299
4298
  boxes: [
4300
4299
  {
@@ -4329,38 +4328,38 @@ Presenter Notes:
4329
4328
  pos: [670, 150, 530, 510]
4330
4329
  -->
4331
4330
 
4332
- ## \u2696\uFE0F So S\xE1nh Kh\xE1i Ni\u1EC7m & Gi\u1EA3i Ph\xE1p
4331
+ ## \u2696\uFE0F Monolithic Polling vs Event-Driven Architecture
4333
4332
 
4334
4333
  <div class="columns-2">
4335
4334
  <div>
4336
4335
 
4337
- ### \u{1F534} C\xE1ch Ti\u1EBFp C\u1EADn C\u0169
4338
- - X\u1EED l\xFD th\u1EE7 c\xF4ng, t\u1ED1n nhi\u1EC1u nh\xE2n l\u1EF1c
4339
- - D\u1EC5 ph\xE1t sinh sai s\u1ED1 do thao t\xE1c l\u1EB7p l\u1EA1i
4340
- - Kh\xF3 m\u1EDF r\u1ED9ng khi t\u1EA3i t\u0103ng \u0111\u1ED9t bi\u1EBFn
4336
+ ### \u{1F534} Legacy Polling
4337
+ - Heavy database CPU overhead on idle cycles
4338
+ - High network latency between updates
4339
+ - Prone to cascading timeouts during spikes
4341
4340
 
4342
4341
  </div>
4343
4342
  <div>
4344
4343
 
4345
- ### \u{1F7E2} Gi\u1EA3i Ph\xE1p T\u1ED1i \u01AFu M\u1EDBi
4346
- - T\u1EF1 \u0111\u1ED9ng h\xF3a ho\xE0n to\xE0n lu\u1ED3ng x\u1EED l\xFD
4347
- - Gi\xE1m s\xE1t tr\u1EA1ng th\xE1i th\u1EDDi gian th\u1EF1c
4348
- - Kh\u1EA3 n\u0103ng co gi\xE3n linh ho\u1EA1t theo nhu c\u1EA7u
4344
+ ### \u{1F7E2} Event-Driven Streams
4345
+ - Real-time event propagation via webhooks
4346
+ - Zero idle compute waste with serverless consumers
4347
+ - Automatic backpressure and queue isolation
4349
4348
 
4350
4349
  </div>
4351
4350
  </div>
4352
4351
 
4353
4352
  <!--
4354
4353
  Presenter Notes:
4355
- - Nh\u1EA5n m\u1EA1nh \u0111i\u1EC3m ngh\u1EBDn l\u1EDBn nh\u1EA5t \u1EDF c\u1ED9t b\xEAn tr\xE1i.
4356
- - D\u1EABn ch\u1EE9ng s\u1ED1 li\u1EC7u th\u1EF1c t\u1EBF ch\u1EE9ng minh t\xEDnh hi\u1EC7u qu\u1EA3 c\u1EE7a c\u1ED9t ph\u1EA3i.
4354
+ - Emphasize the core failure mode of periodic polling under sudden load spikes.
4355
+ - Ask the room if anyone has experienced database lockups caused by polling loops.
4357
4356
  -->`
4358
4357
  },
4359
4358
  {
4360
4359
  id: "code-explainer",
4361
- name: "Gi\u1EA3i Th\xEDch Code (Code Walkthrough)",
4360
+ name: "Code Walkthrough & Analysis",
4362
4361
  category: "code",
4363
- description: "C\u1ED9t tr\xE1i hi\u1EC3n th\u1ECB code snippet c\xF3 \u0111\xE1nh s\u1ED1, c\u1ED9t ph\u1EA3i gi\u1EA3i th\xEDch t\u1EEBng b\u01B0\u1EDBc ho\u1EA1t \u0111\u1ED9ng.",
4362
+ description: "Syntax-highlighted code block on the left with step-by-step key annotations on the right.",
4364
4363
  layout: {
4365
4364
  boxes: [
4366
4365
  {
@@ -4395,16 +4394,16 @@ Presenter Notes:
4395
4394
  pos: [740, 135, 460, 535]
4396
4395
  -->
4397
4396
 
4398
- ## \u{1F4BB} Ph\xE2n T\xEDch C\u1EA5u Tr\xFAc M\xE3 Ngu\u1ED3n
4397
+ ## \u{1F4BB} Robust Async Transaction Pipeline
4399
4398
 
4400
4399
  <div class="columns-2">
4401
4400
  <div>
4402
4401
 
4403
4402
  \`\`\`ts
4404
- // Kh\u1EDFi t\u1EA1o quy tr\xECnh ki\u1EC3m tra d\u1EEF li\u1EC7u
4403
+ // Process payment with idempotency guarantee
4405
4404
  export async function processPayment(order: Order) {
4406
4405
  const isValid = await validateOrder(order);
4407
- if (!isValid) throw new Error("Invalid");
4406
+ if (!isValid) throw new Error("ValidationFailed");
4408
4407
 
4409
4408
  const receipt = await chargeCard(order);
4410
4409
  return sendConfirmation(receipt);
@@ -4414,25 +4413,26 @@ export async function processPayment(order: Order) {
4414
4413
  </div>
4415
4414
  <div>
4416
4415
 
4417
- ### \u{1F50D} 3 \u0110i\u1EC3m C\u1EA7n Ch\xFA \xDD:
4418
- 1. **Ki\u1EC3m tra s\u1EDBm (Guard Clause):** Ki\u1EC3m tra t\xEDnh h\u1EE3p l\u1EC7 ngay d\xF2ng 3 \u0111\u1EC3 tr\xE1nh g\u1ECDi h\xE0m t\u1ED1n chi ph\xED.
4419
- 2. **B\u1EA5t \u0111\u1ED3ng b\u1ED9 (Async/Await):** \u0110\u1EA3m b\u1EA3o th\u1EE9 t\u1EF1 g\u1ECDi API t\xE0i ch\xEDnh chu\u1EA9n x\xE1c.
4420
- 3. **Ph\u1EA3n h\u1ED3i ng\u01B0\u1EDDi d\xF9ng:** Tr\u1EA3 v\u1EC1 bi\xEAn lai ho\xE0n ch\u1EC9nh sau khi giao d\u1ECBch th\xE0nh c\xF4ng.
4416
+ ### \u{1F50D} Key Engineering Invariants:
4417
+ 1. **Early Guard Clause:** Validates payload immediately at line 3 before triggering external calls.
4418
+ 2. **Deterministic Sequence:** Enforces strict order of operations using native \`await\`.
4419
+ 3. **Audit Trail:** Returns immutable payment receipt upon successful execution.
4421
4420
 
4422
4421
  </div>
4423
4422
  </div>
4424
4423
 
4425
4424
  <!--
4426
4425
  Presenter Notes:
4427
- - Y\xEAu c\u1EA7u h\u1ECDc vi\xEAn x\xE1c \u0111\u1ECBnh d\xF2ng code n\xE0o l\xE0 r\u1EE7i ro nh\u1EA5t n\u1EBFu k\u1EBFt n\u1ED1i m\u1EA1ng b\u1ECB r\u1EDBt.
4428
- - Nh\u1EAFc l\u1EA1i nguy\xEAn t\u1EAFc Fail-Fast trong l\u1EADp tr\xECnh ph\xF2ng th\u1EE7.
4426
+ - Walk through lines 1 to 7 sequentially.
4427
+ - Cold-call check: "What happens if line 6 throws a network timeout?"
4428
+ - Cognitive scaffolding: Highlight the importance of idempotency keys in payment APIs.
4429
4429
  -->`
4430
4430
  },
4431
4431
  {
4432
4432
  id: "metrics-3-card",
4433
- name: "L\u01B0\u1EDBi 3 Ch\u1EC9 S\u1ED1 (3-Metric Dashboard)",
4433
+ name: "3-Metric Key Results Grid",
4434
4434
  category: "metrics",
4435
- description: "Hi\u1EC3n th\u1ECB 3 ch\u1EC9 s\u1ED1 quan tr\u1ECDng (KPIs, Benchmarks, Impact) d\u1EA1ng card n\u1ED5i b\u1EADt.",
4435
+ description: "Three high-visibility KPI stat cards for benchmarks, impact, and success criteria.",
4436
4436
  layout: {
4437
4437
  boxes: [
4438
4438
  {
@@ -4477,43 +4477,43 @@ Presenter Notes:
4477
4477
  pos: [860, 165, 340, 485]
4478
4478
  -->
4479
4479
 
4480
- ## \u{1F4CA} 3 Ch\u1EC9 S\u1ED1 Th\xE0nh C\xF4ng C\u1EE7a D\u1EF1 \xC1n
4480
+ ## \u{1F4CA} Performance & Reliability Benchmarks
4481
4481
 
4482
4482
  <div class="columns-3">
4483
4483
  <div>
4484
4484
 
4485
- # \u26A1 99.9%
4486
- ### \u0110\u1ED9 S\u1EB5n S\xE0ng (Uptime)
4487
- H\u1EC7 th\u1ED1ng v\u1EADn h\xE0nh li\xEAn t\u1EE5c 24/7 v\u1EDBi kh\u1EA3 n\u0103ng t\u1EF1 ph\u1EE5c h\u1ED3i l\u1ED7i t\u1EE9c th\xEC.
4485
+ # \u26A1 99.99%
4486
+ ### SLA Availability
4487
+ High-availability multi-region cluster with automated failover routing.
4488
4488
 
4489
4489
  </div>
4490
4490
  <div>
4491
4491
 
4492
- # \u{1F680} 10x
4493
- ### T\u1ED1c \u0110\u1ED9 X\u1EED L\xFD
4494
- R\xFAt ng\u1EAFn th\u1EDDi gian bi\xEAn d\u1ECBch v\xE0 ph\u1EA3n h\u1ED3i ng\u01B0\u1EDDi d\xF9ng t\u1EEB gi\xE2y xu\u1ED1ng mili-gi\xE2y.
4492
+ # \u{1F680} 15ms
4493
+ ### P99 Latency
4494
+ Sub-20ms roundtrip response time via distributed edge caching.
4495
4495
 
4496
4496
  </div>
4497
4497
  <div>
4498
4498
 
4499
- # \u{1F6E1}\uFE0F 0
4500
- ### L\u1ED7 H\u1ED5ng B\u1EA3o M\u1EADt
4501
- \u0110\u1EA1t chu\u1EA9n \u0111\xE1nh gi\xE1 an to\xE0n OWASP v\xE0 m\xE3 h\xF3a d\u1EEF li\u1EC7u \u0111\u1EA7u cu\u1ED1i.
4499
+ # \u{1F6E1}\uFE0F Zero
4500
+ ### Unhandled Breaches
4501
+ Full SOC2 Type II compliance and end-to-end payload encryption.
4502
4502
 
4503
4503
  </div>
4504
4504
  </div>
4505
4505
 
4506
4506
  <!--
4507
4507
  Presenter Notes:
4508
- - Tr\xECnh b\xE0y l\u1EA7n l\u01B0\u1EE3t 3 m\u1EE5c ti\xEAu \u0111o l\u01B0\u1EDDng \u0111\u01B0\u1EE3c c\u1EE7a h\u1EC7 th\u1ED1ng.
4509
- - Nh\u1EA5n m\u1EA1nh ch\u1EC9 s\u1ED1 th\u1EE9 2 l\xE0 tr\u1ECDng t\xE2m k\u1EF9 thu\u1EADt c\u1EE7a b\xE0i h\u1ECDc h\xF4m nay.
4508
+ - Highlight the 15ms P99 latency target as the primary technical milestone.
4509
+ - Connect these metrics directly to the architecture decisions discussed next.
4510
4510
  -->`
4511
4511
  },
4512
4512
  {
4513
4513
  id: "process-flow",
4514
- name: "S\u01A1 \u0110\u1ED3 Quy Tr\xECnh (Process / Flowchart)",
4514
+ name: "Architecture & Process Flow",
4515
4515
  category: "diagram",
4516
- description: "Quy tr\xECnh nhi\u1EC1u b\u01B0\u1EDBc v\u1EDBi s\u01A1 \u0111\u1ED3 Mermaid tr\u1EF1c quan k\xE8m ghi ch\xFA t\xF3m t\u1EAFt.",
4516
+ description: "Multi-stage workflow with responsive Mermaid diagram and phase summaries.",
4517
4517
  layout: {
4518
4518
  boxes: [
4519
4519
  {
@@ -4548,33 +4548,33 @@ Presenter Notes:
4548
4548
  pos: [80, 465, 1120, 205]
4549
4549
  -->
4550
4550
 
4551
- ## \u{1F504} Ki\u1EBFn Tr\xFAc Lu\u1ED3ng D\u1EEF Li\u1EC7u 4 B\u01B0\u1EDBc
4551
+ ## \u{1F504} End-to-End Data Ingestion Pipeline
4552
4552
 
4553
4553
  \`\`\`mermaid
4554
4554
  graph LR
4555
- A[1. Client Request] --> B[2. API Gateway]
4556
- B --> C[3. Auth Service]
4557
- C --> D[4. Database Cluster]
4555
+ A[1. Client Ingress] --> B[2. API Gateway]
4556
+ B --> C[3. Auth Verifier]
4557
+ C --> D[4. Distributed DB]
4558
4558
  style A fill:#0284c7,stroke:#38bdf8,stroke-width:2px,color:#fff
4559
4559
  style B fill:#1e293b,stroke:#64748b,stroke-width:2px,color:#fff
4560
4560
  style C fill:#059669,stroke:#34d399,stroke-width:2px,color:#fff
4561
4561
  style D fill:#7c3aed,stroke:#a78bfa,stroke-width:2px,color:#fff
4562
4562
  \`\`\`
4563
4563
 
4564
- - **Giai \u0111o\u1EA1n 1 & 2:** Ti\u1EBFp nh\u1EADn y\xEAu c\u1EA7u t\u1EEB client, \u0111i\u1EC1u h\u01B0\u1EDBng t\u1EA3i v\xE0 gi\u1EDBi h\u1EA1n t\u1EA7n su\u1EA5t (Rate Limiting).
4565
- - **Giai \u0111o\u1EA1n 3 & 4:** X\xE1c th\u1EF1c token JWT ph\xE2n quy\u1EC1n tr\u01B0\u1EDBc khi truy v\u1EA5n d\u1EEF li\u1EC7u t\u1EEB DB Cluster.
4564
+ - **Ingress & Gateway:** Rate-limits traffic and applies reverse-proxy load balancing.
4565
+ - **Verification & Storage:** Decodes cryptographic JWT tokens before transactional write commit.
4566
4566
 
4567
4567
  <!--
4568
4568
  Presenter Notes:
4569
- - Tr\u1ECF tr\u1EF1c ti\u1EBFp v\xE0o t\u1EEBng node c\u1EE7a s\u01A1 \u0111\u1ED3 Mermaid khi thuy\u1EBFt tr\xECnh.
4570
- - \u0110\u1EB7t c\xE2u h\u1ECFi: "N\u1EBFu b\u01B0\u1EDBc 3 th\u1EA5t b\u1EA1i th\xEC b\u01B0\u1EDBc 4 c\xF3 \u0111\u01B0\u1EE3c g\u1ECDi kh\xF4ng?"
4569
+ - Trace each hop across the diagram from left to right.
4570
+ - Ask: "Where should rate limiting be applied to prevent DDoS attacks?"
4571
4571
  -->`
4572
4572
  },
4573
4573
  {
4574
4574
  id: "quote-highlight",
4575
- name: "Th\xF4ng \u0110i\u1EC7p Then Ch\u1ED1t (Quote / Highlight)",
4575
+ name: "Core Principle & Quote Highlight",
4576
4576
  category: "quote",
4577
- description: "Tr\xEDch d\u1EABn danh ng\xF4n ho\u1EB7c nguy\xEAn t\u1EAFc v\xE0ng c\u1EA7n ghi nh\u1EDB s\xE2u s\u1EAFc.",
4577
+ description: "Prominent quote callout for fundamental engineering rules or memorable mantras.",
4578
4578
  layout: {
4579
4579
  boxes: [
4580
4580
  {
@@ -4605,23 +4605,23 @@ Presenter Notes:
4605
4605
  fontSize: 1.4rem
4606
4606
  -->
4607
4607
 
4608
- ## \u{1F4A1} Nguy\xEAn T\u1EAFc Thi\u1EBFt K\u1EBF C\u1ED1t L\xF5i
4608
+ ## \u{1F4A1} Foundational Architecture Principle
4609
4609
 
4610
- > "S\u1EF1 \u0111\u01A1n gi\u1EA3n l\xE0 \u0111i\u1EC1u ki\u1EC7n ti\xEAn quy\u1EBFt cho \u0111\u1ED9 tin c\u1EADy. M\u1ED9t ki\u1EBFn tr\xFAc t\u1ED1t l\xE0 khi b\u1EA5t k\u1EF3 l\u1EADp tr\xECnh vi\xEAn m\u1EDBi n\xE0o c\u0169ng c\xF3 th\u1EC3 \u0111\u1ECDc hi\u1EC3u lu\u1ED3ng ho\u1EA1t \u0111\u1ED9ng ch\u1EC9 sau 15 ph\xFAt."
4610
+ > "Simplicity is prerequisite for reliability. A well-engineered distributed system is one where a new engineer can understand the request flow within their first hour."
4611
4611
  >
4612
4612
  > \u2014 **Edsger W. Dijkstra**
4613
4613
 
4614
4614
  <!--
4615
4615
  Presenter Notes:
4616
- - D\u1EEBng l\u1EA1i 5 gi\xE2y im l\u1EB7ng \u0111\u1EC3 c\u1EA3 l\u1EDBp c\xF9ng suy ng\u1EABm v\u1EC1 th\xF4ng \u0111i\u1EC7p.
4617
- - Y\xEAu c\u1EA7u m\u1ED9t h\u1ECDc vi\xEAn chia s\u1EBB suy ngh\u0129 v\u1EC1 c\xE1ch \xE1p d\u1EE5ng nguy\xEAn t\u1EAFc n\xE0y v\xE0o b\xE0i t\u1EADp l\u1EDBn.
4616
+ - Pause for 5 seconds of silence to let the quote sink in.
4617
+ - Ask: "How do our current architectural choices reflect this principle?"
4618
4618
  -->`
4619
4619
  },
4620
4620
  {
4621
4621
  id: "quiz-checkpoint",
4622
- name: "Tr\u1EAFc Nghi\u1EC7m T\u01B0\u01A1ng T\xE1c (Quiz Checkpoint)",
4622
+ name: "Interactive Formative Checkpoint",
4623
4623
  category: "assessment",
4624
- description: "C\xE2u h\u1ECFi t\u01B0\u01A1ng t\xE1c Formative Checkpoint k\xE8m c\xE1c l\u1EF1a ch\u1ECDn A/B/C/D \u0111\u1EC3 l\u1EDBp b\xECnh ch\u1ECDn.",
4624
+ description: "Interactive multiple-choice diagnostic checkpoint with A/B/C/D voting options.",
4625
4625
  layout: {
4626
4626
  boxes: [
4627
4627
  {
@@ -4660,27 +4660,27 @@ Presenter Notes:
4660
4660
  fontSize: 1.15rem
4661
4661
  -->
4662
4662
 
4663
- ## \u{1F3AF} Ki\u1EC3m Tra Nhanh: B\u1EA1n \u0110\xE3 Hi\u1EC3u \u0110\xFAng?
4663
+ ## \u{1F3AF} Formative Checkpoint: Verify Your Understanding
4664
4664
 
4665
- > **C\xE2u h\u1ECFi:** Trong ki\u1EBFn tr\xFAc Microservices, c\u01A1 ch\u1EBF n\xE0o gi\xFAp \u0111\u1EA3m b\u1EA3o tin nh\u1EAFn kh\xF4ng b\u1ECB th\u1EA5t l\u1EA1c khi d\u1ECBch v\u1EE5 nh\u1EADn g\u1EB7p s\u1EF1 c\u1ED1 t\u1EA1m th\u1EDDi?
4665
+ > **Question:** In an event-driven architecture, which pattern guarantees that messages are never permanently lost if a downstream consumer crashes?
4666
4666
 
4667
- - **A.** G\u1ECDi API HTTP tr\u1EF1c ti\u1EBFp v\u1EDBi timeout ng\u1EAFn
4668
- - **B.** S\u1EED d\u1EE5ng Message Queue (H\xE0ng \u0111\u1EE3i tin nh\u1EAFn) c\xF3 c\u01A1 ch\u1EBF Retry & DLQ
4669
- - **C.** L\u01B0u t\u1EA1m v\xE0o b\u1ED9 nh\u1EDB RAM c\u1EE7a m\xE1y kh\xE1ch (Client In-Memory Storage)
4670
- - **D.** B\u1ECF qua tin nh\u1EAFn b\u1ECB l\u1ED7i v\xE0 th\xF4ng b\xE1o ng\u01B0\u1EDDi d\xF9ng g\u1EEDi l\u1EA1i t\u1EEB \u0111\u1EA7u
4667
+ - **A.** Direct synchronous HTTP request with short 2-second timeout
4668
+ - **B.** Persistent Message Broker with Dead-Letter Queue (DLQ) & retry policy
4669
+ - **C.** In-memory client RAM cache without persistence
4670
+ - **D.** Discarding failed packets and prompting the user to re-submit
4671
4671
 
4672
4672
  <!--
4673
4673
  Presenter Notes:
4674
- - D\xE0nh 30 gi\xE2y cho h\u1ECDc vi\xEAn gi\u01A1 tay ho\u1EB7c b\xECnh ch\u1ECDn \u0111\xE1p \xE1n.
4675
- - \u0110\xE1p \xE1n ch\xEDnh x\xE1c: B.
4676
- - Gi\u1EA3i th\xEDch v\xEC sao \u0111\xE1p \xE1n A v\xE0 C ti\u1EC1m \u1EA9n nguy c\u01A1 m\u1EA5t m\xE1t d\u1EEF li\u1EC7u nghi\xEAm tr\u1ECDng.
4674
+ - Give students 30 seconds to vote on option A, B, C, or D.
4675
+ - Correct answer: B.
4676
+ - Explain why options A and C introduce catastrophic data loss in production.
4677
4677
  -->`
4678
4678
  },
4679
4679
  {
4680
4680
  id: "tiered-practice-3cards",
4681
- name: "Th\u1EF1c H\xE0nh Ph\xE2n H\xF3a (Tiered Practice)",
4681
+ name: "Tiered Differentiation (Bronze / Silver / Gold)",
4682
4682
  category: "content",
4683
- description: "3 c\u1EA5p b\u1EADc nhi\u1EC7m v\u1EE5 \u0110\u1ED3ng - B\u1EA1c - V\xE0ng \u0111\u1EC3 h\u1ECDc sinh t\u1EF1 ch\u1ECDn m\u1EE9c th\u1EED th\xE1ch ph\xF9 h\u1EE3p.",
4683
+ description: "Three progressive competency tiers allowing self-paced learning acceleration.",
4684
4684
  layout: {
4685
4685
  boxes: [
4686
4686
  {
@@ -4723,46 +4723,46 @@ Presenter Notes:
4723
4723
  pos: [850, 140, 350, 520]
4724
4724
  -->
4725
4725
 
4726
- ## \u{1F6E0}\uFE0F Th\u1EED Th\xE1ch Ph\xE2n H\xF3a 3 C\u1EA5p \u0110\u1ED9 (Tiered Lab)
4726
+ ## \u{1F6E0}\uFE0F Hands-On Challenge: 3-Tier Differentiation
4727
4727
 
4728
4728
  <div class="columns-3">
4729
4729
  <div>
4730
4730
 
4731
- ### \u{1F949} H\u1EA1ng \u0110\u1ED3ng (Bronze)
4732
- - Vi\u1EBFt h\xE0m x\u1EED l\xFD c\u01A1 b\u1EA3n
4733
- - V\u01B0\u1EE3t qua 3 test case m\u1EABu
4734
- - *M\u1EE5c ti\xEAu: \u0110\u1EA1t chu\u1EA9n ki\u1EBFn th\u1EE9c c\u01A1 b\u1EA3n*
4731
+ ### \u{1F949} Bronze Tier
4732
+ - Implement baseline function
4733
+ - Pass 3 baseline unit tests
4734
+ - *Goal: Foundational mastery*
4735
4735
 
4736
4736
  </div>
4737
4737
  <div>
4738
4738
 
4739
- ### \u{1F948} H\u1EA1ng B\u1EA1c (Silver)
4740
- - Th\xEAm ki\u1EC3m tra \u0111i\u1EC1u ki\u1EC7n bi\xEAn
4741
- - T\u1ED1i \u01B0u \u0111\u1ED9 ph\u1EE9c t\u1EA1p thu\u1EADt to\xE1n O(N)
4742
- - *M\u1EE5c ti\xEAu: V\u1EEFng v\xE0ng k\u1EF9 n\u0103ng th\u1EF1c chi\u1EBFn*
4739
+ ### \u{1F948} Silver Tier
4740
+ - Add boundary error handling
4741
+ - Enforce O(N) memory complexity
4742
+ - *Goal: Production-ready code*
4743
4743
 
4744
4744
  </div>
4745
4745
  <div>
4746
4746
 
4747
- ### \u{1F947} H\u1EA1ng V\xE0ng (Gold)
4748
- - Thi\u1EBFt k\u1EBF t\xEDnh n\u0103ng m\u1EDF r\u1ED9ng
4749
- - Vi\u1EBFt Unit Test t\u1EF1 \u0111\u1ED9ng bao ph\u1EE7 90%
4750
- - *M\u1EE5c ti\xEAu: S\xE1ng t\u1EA1o & b\u1EE9t ph\xE1*
4747
+ ### \u{1F947} Gold Tier
4748
+ - Design distributed retry queue
4749
+ - Add 95% automated test coverage
4750
+ - *Goal: Architectural leadership*
4751
4751
 
4752
4752
  </div>
4753
4753
  </div>
4754
4754
 
4755
4755
  <!--
4756
4756
  Presenter Notes:
4757
- - To\xE0n b\u1ED9 l\u1EDBp \u0111\u1EC1u b\u1EAFt \u0111\u1EA7u t\u1EEB H\u1EA1ng \u0110\u1ED3ng \u0111\u1EC3 \u0111\u1EA3m b\u1EA3o hi\u1EC3u b\xE0i.
4758
- - Khuy\u1EBFn kh\xEDch h\u1ECDc vi\xEAn \u0111\xE3 xong Bronze ch\u1EE7 \u0111\u1ED9ng th\u1EED s\u1EE9c v\u1EDBi Silver v\xE0 Gold.
4757
+ - All learners begin at Bronze to establish baseline competency.
4758
+ - Accelerate self-directed learners to Silver and Gold as they complete each tier.
4759
4759
  -->`
4760
4760
  },
4761
4761
  {
4762
4762
  id: "agenda-timeline",
4763
- name: "L\u1ED9 Tr\xECnh Bu\u1ED5i H\u1ECDc (Agenda Table)",
4763
+ name: "Session Agenda & Milestones",
4764
4764
  category: "content",
4765
- description: "B\u1EA3ng l\u1ED9 tr\xECnh th\u1EDDi gian chi ti\u1EBFt theo t\u1EEBng giai \u0111o\u1EA1n v\xE0 s\u1EA3n ph\u1EA9m \u0111\u1EA7u ra.",
4765
+ description: "Structured time-budgeted agenda mapping stages to measurable deliverables.",
4766
4766
  layout: {
4767
4767
  boxes: [
4768
4768
  {
@@ -4789,25 +4789,25 @@ Presenter Notes:
4789
4789
  pos: [80, 140, 1120, 520]
4790
4790
  -->
4791
4791
 
4792
- ## \u{1F5FA}\uFE0F L\u1ED9 Tr\xECnh Ho\u1EA1t \u0110\u1ED9ng & M\u1EE5c Ti\xEAu
4792
+ ## \u{1F5FA}\uFE0F Milestone Roadmap & Time Budget
4793
4793
 
4794
- | Th\u1EDDi l\u01B0\u1EE3ng | Giai \u0111o\u1EA1n | Tr\u1ECDng t\xE2m ho\u1EA1t \u0111\u1ED9ng | K\u1EBFt qu\u1EA3 \u0111\u1EA1t \u0111\u01B0\u1EE3c |
4794
+ | Allocated Time | Session Stage | Core Learning Focus | Deliverable Milestone |
4795
4795
  |:---:|---|---|---|
4796
- | **05'** | Kh\u1EDFi \u0111\u1ED9ng | T\xECnh hu\u1ED1ng th\u1EF1c t\u1EBF & Th\u1EED th\xE1ch | Nh\u1EADn di\u1EC7n b\xE0i to\xE1n c\u1EA7n gi\u1EA3i |
4797
- | **15'** | Kh\xE1m ph\xE1 | Ph\xE2n t\xEDch 2 kh\xE1i ni\u1EC7m c\u1ED1t l\xF5i | Hi\u1EC3u b\u1EA3n ch\u1EA5t thu\u1EADt to\xE1n |
4798
- | **20'** | Th\u1EF1c h\xE0nh | Code Lab t\u1EA1i m\xE1y theo 3 b\u1EADc | Ho\xE0n th\xE0nh t\u1ED1i thi\u1EC3u H\u1EA1ng \u0110\u1ED3ng |
4799
- | **05'** | T\u1ED5ng k\u1EBFt | Tr\u1EAFc nghi\u1EC7m ph\u1EA3n x\u1EA1 & \u0110\xE1nh gi\xE1 | H\u1EC7 th\u1ED1ng h\xF3a to\xE0n b\u1ED9 ki\u1EBFn th\u1EE9c |
4796
+ | **05 mins** | Warm-Up | Real-World Scenario & Context | Identify system bottleneck |
4797
+ | **15 mins** | Concept Discovery | Core Architectural Patterns | Deconstruct message queue models |
4798
+ | **20 mins** | Hands-On Lab | Tiered Code Implementation | Complete Bronze + Silver tasks |
4799
+ | **05 mins** | Wrap-Up | Formative Checkpoint & Debrief | Consolidate key principles |
4800
4800
 
4801
4801
  <!--
4802
4802
  Presenter Notes:
4803
- - Gi\u1EDBi thi\u1EC7u t\u1ED5ng quan \u0111\u1EC3 h\u1ECDc vi\xEAn bi\u1EBFt r\xF5 c\u1EA5u tr\xFAc bu\u1ED5i h\u1ECDc v\xE0 ch\u1EE7 \u0111\u1ED9ng ph\xE2n b\u1ED5 th\u1EDDi gian.
4803
+ - Walk through the time budget so students understand expectations and pacing.
4804
4804
  -->`
4805
4805
  },
4806
4806
  {
4807
4807
  id: "takeaways-summary",
4808
- name: "T\u1ED5ng K\u1EBFt C\u1ED1t L\xF5i (Key Takeaways)",
4808
+ name: "Key Takeaways & Wrap-up",
4809
4809
  category: "content",
4810
- description: "Slide k\u1EBFt lu\u1EADn v\u1EDBi 3 b\xE0i h\u1ECDc \u0111\u1EAFt gi\xE1 nh\u1EA5t v\xE0 h\xE0nh \u0111\u1ED9ng ti\u1EBFp theo.",
4810
+ description: "Three memorable synthesis takeaways with actionable next steps.",
4811
4811
  layout: {
4812
4812
  boxes: [
4813
4813
  {
@@ -4846,18 +4846,18 @@ Presenter Notes:
4846
4846
  fontSize: 1.1rem
4847
4847
  -->
4848
4848
 
4849
- ## \u{1F3C1} 3 \u0110i\u1EC1u C\u1EA7n Nh\u1EDB Sau Bu\u1ED5i H\u1ECDc
4849
+ ## \u{1F3C1} Key Takeaways & Action Items
4850
4850
 
4851
- 1. **Hi\u1EC3u b\u1EA3n ch\u1EA5t tr\u01B0\u1EDBc khi vi\u1EBFt m\xE3:** Thu\u1EADt to\xE1n \u0111\xFAng lu\xF4n quan tr\u1ECDng h\u01A1n c\xFA ph\xE1p b\xF3ng b\u1EA9y.
4852
- 2. **Ki\u1EC3m so\xE1t \u0111i\u1EC1u ki\u1EC7n bi\xEAn:** 80% l\u1ED7i h\u1EC7 th\u1ED1ng ph\xE1t sinh t\u1EEB c\xE1c d\u1EEF li\u1EC7u \u0111\u1EA7u v\xE0o kh\xF4ng l\u01B0\u1EDDng tr\u01B0\u1EDBc.
4853
- 3. **Thi\u1EBFt k\u1EBF h\u01B0\u1EDBng m\xF4-\u0111un:** Chia nh\u1ECF v\u1EA5n \u0111\u1EC1 l\u1EDBn th\xE0nh c\xE1c h\xE0m \u0111\u1ED9c l\u1EADp d\u1EC5 ki\u1EC3m th\u1EED.
4851
+ 1. **Decouple Before Scaling:** Separate producer rate from consumer processing capacity.
4852
+ 2. **Design for Failure:** Always configure retries, backoff intervals, and dead-letter queues.
4853
+ 3. **Measure End-to-End:** Track P99 latency and error rates across all distributed boundaries.
4854
4854
 
4855
- > \u{1F4DD} **Nhi\u1EC7m v\u1EE5 v\u1EC1 nh\xE0:** Ho\xE0n thi\u1EC7n b\xE0i th\u1EF1c h\xE0nh H\u1EA1ng B\u1EA1c v\xE0 chu\u1EA9n b\u1ECB c\xE2u h\u1ECFi cho bu\u1ED5i Review tu\u1EA7n t\u1EDBi.
4855
+ > \u{1F4DD} **Next Action Item:** Complete the Silver Tier refactoring challenge before our next peer-review session.
4856
4856
 
4857
4857
  <!--
4858
4858
  Presenter Notes:
4859
- - T\xF3m t\u1EAFt s\xFAc t\xEDch trong 2 ph\xFAt cu\u1ED1i bu\u1ED5i.
4860
- - Tuy\xEAn d\u01B0\u01A1ng c\xE1c b\u1EA1n c\xF3 gi\u1EA3i ph\xE1p xu\u1EA5t s\u1EAFc trong ph\u1EA7n th\u1EF1c h\xE0nh.
4859
+ - Deliver a crisp 2-minute wrap-up reinforcing the 3 core takeaways.
4860
+ - Acknowledge strong peer collaboration during the hands-on lab.
4861
4861
  -->`
4862
4862
  }
4863
4863
  ];
@@ -9546,14 +9546,14 @@ init_errors();
9546
9546
 
9547
9547
  // src/workflow/gateSettings.ts
9548
9548
  var DEFAULT_GATE_SETTINGS = Object.freeze({
9549
- LEARNER_PROFILE: "HITL",
9550
- PROJECT_BRIEF: "HITL",
9551
- REFERENCE_PACK: "HITL",
9552
- CURRICULUM_FRAMEWORK: "HITL",
9553
- KNOWLEDGE_EXPOSITION: "LLM_JUDGE",
9554
- STYLE_GUIDE: "HITL",
9555
- ART_DIRECTION: "HITL",
9556
- LESSON: "LLM_JUDGE",
9549
+ LEARNER_PROFILE: "OFF",
9550
+ PROJECT_BRIEF: "OFF",
9551
+ REFERENCE_PACK: "OFF",
9552
+ CURRICULUM_FRAMEWORK: "OFF",
9553
+ KNOWLEDGE_EXPOSITION: "OFF",
9554
+ STYLE_GUIDE: "OFF",
9555
+ ART_DIRECTION: "OFF",
9556
+ LESSON: "OFF",
9557
9557
  ACT: "OFF",
9558
9558
  QUIZ: "OFF",
9559
9559
  SLIDE: "OFF",
@@ -9561,7 +9561,7 @@ var DEFAULT_GATE_SETTINGS = Object.freeze({
9561
9561
  WKS: "OFF",
9562
9562
  HANDOUT: "OFF",
9563
9563
  EXT: "OFF",
9564
- CODE: "LLM_JUDGE",
9564
+ CODE: "OFF",
9565
9565
  MEDIA_SCRIPT: "OFF",
9566
9566
  EXIT_TICKET: "OFF"
9567
9567
  });
@@ -11450,9 +11450,10 @@ Fix ALL issues above and output the complete corrected document.` }],
11450
11450
  const taskState = pipelineState.tasks[lessonCode] || {};
11451
11451
  const currentLessonInfo = taskState.LESSON;
11452
11452
  const lessonGate = gateModeFor(gates, "LESSON");
11453
- let isLessonApproved = lessonGate !== "HITL" || // OFF/LLM_JUDGE: không cần duyệt người
11454
- currentLessonInfo?.state === "approved" || currentLessonInfo?.review?.decision === "APPROVED" || approvedArtifacts.includes("LESSON") || approvedArtifacts.includes(lessonCode);
11455
- if (lessonGate === "LLM_JUDGE" && !isLessonApproved && lessonContent) {
11453
+ const humanApproved = currentLessonInfo?.state === "approved" || currentLessonInfo?.review?.decision === "APPROVED" || approvedArtifacts.includes("LESSON") || approvedArtifacts.includes(lessonCode);
11454
+ const needsJudge = lessonGate === "LLM_JUDGE" && !humanApproved;
11455
+ let isLessonApproved = lessonGate === "OFF" || humanApproved;
11456
+ if (needsJudge && lessonContent) {
11456
11457
  onProgress?.("@reviewer", `\u{1F916} Executing LLM-as-Judge academic evaluation on LESSON_${lessonCode}.md...`);
11457
11458
  try {
11458
11459
  let injectYamlReviewMetadata2 = function(content, meta) {
@@ -12491,6 +12492,8 @@ async function generateSingleArtifact(req) {
12491
12492
  extraContext,
12492
12493
  config,
12493
12494
  contextSot = {},
12495
+ mediaPolicy,
12496
+ researchContext,
12494
12497
  options = {},
12495
12498
  onChunk
12496
12499
  } = req;
@@ -12528,7 +12531,10 @@ ${langRule}
12528
12531
  3. PEDAGOGICAL GROUNDING: Strictly align with the ${pedagogy.toUpperCase()} model, Bloom's Revised Taxonomy, and IEEE/ACM CS2023 guidelines.
12529
12532
  4. SCAFFOLDING LEVEL: "${scaffoldingLevel.toUpperCase()}".${scaffoldingRule}
12530
12533
  5. TARGET AUDIENCE: ${gradeLevel ? `Grade ${gradeLevel}, ` : ""}${targetAge} on ${hwStr}.${deviceRule}${classDynamicsRule}${extraContextRule}
12531
- 6. OUTPUT INTEGRITY: Output clean Markdown starting directly with YAML frontmatter. Do not wrap entire response in triple backticks.${artifactSpecializedPrompt}`;
12534
+ 6. OUTPUT INTEGRITY: Output clean Markdown starting directly with YAML frontmatter. Do not wrap entire response in triple backticks.${artifactSpecializedPrompt}${mediaPolicy ? `
12535
+
12536
+ IMAGE PLANNING (media ledger) \u2014 QUOTA GEN: t\u1ED1i \u0111a ${mediaPolicy.maxGenImagesPerArtifact} \u1EA3nh AI cho artifact n\xE0y (\u1EA3nh search kho kh\xF4ng gi\u1EDBi h\u1EA1n).
12537
+ Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u1ED3 kh\xE1i ni\u1EC7m, step-by-step visual), ch\xE8n placeholder \u0111\xFAng format [IMAGE: slug] (slug ch\u1EEF th\u01B0\u1EDDng-g\u1EA1ch ngang, unique trong b\xE0i, vd img-for-loop-diagram) T\u1EA0I \u0110\xDANG CH\u1ED6 c\u1EA7n \u1EA3nh, tr\xEAn d\xF2ng ri\xEAng. KH\xD4NG t\u1EF1 sinh \u1EA3nh, KH\xD4NG d\xF9ng markdown image \u2014 placeholder s\u1EBD \u0111\u01B0\u1EE3c thay b\u1EB1ng \u1EA3nh th\u1EADt sau khi Media Curator duy\u1EC7t. Ch\u1EC9 \u0111\u1EB7t cho \u1EA3nh TH\u1EF0C S\u1EF0 c\u1EA7n thi\u1EBFt.` : ""}`;
12532
12538
  const userPrompt = `### CONTEXT GROUND TRUTH:
12533
12539
  - Topic / Concept Domain: "${topic}"
12534
12540
  - Lesson ID: "${lessonId || "ON_DEMAND"}"
@@ -12543,6 +12549,9 @@ ${selectedDevices ? `- Device Mode: "${selectedDevices}"
12543
12549
  ` : ""}${extraContext ? `- User Specific Guidance & Requirements: "${extraContext}"
12544
12550
  ` : ""}${config ? `- Full Task Config: ${JSON.stringify(config)}
12545
12551
  ` : ""}
12552
+ ${researchContext ? `### RESEARCH GROUND TRUTH (fact-checked context \u2014 \u01B0u ti\xEAn d\xF9ng, KH\xD4NG b\u1ECBa s\u1ED1 li\u1EC7u):
12553
+ ${researchContext.slice(0, 4e3)}
12554
+ ` : ""}
12546
12555
  ${contextSot.framework ? `### SOT CURRICULUM FRAMEWORK:
12547
12556
  ${contextSot.framework.slice(0, 1500)}
12548
12557
  ` : ""}
@@ -12583,13 +12592,171 @@ Generate the complete, thorough, publication-grade "${artifactType.toUpperCase()
12583
12592
  }
12584
12593
  );
12585
12594
  const { thought, content } = extractThoughtAndContent(rawResult);
12586
- return {
12587
- artifactType,
12588
- filename: meta.filename,
12589
- content: content || accumulatedContent,
12590
- persona: meta.persona,
12591
- thought: thought || accumulatedThought
12595
+ const finalContent = content || accumulatedContent;
12596
+ const finalThought = thought || accumulatedThought;
12597
+ const gates = resolveGateSettings(req.gateSettings);
12598
+ const kitGateType = {
12599
+ lesson: "LESSON",
12600
+ slide: "SLIDE",
12601
+ act: "ACT",
12602
+ quiz: "QUIZ",
12603
+ guide: "GUIDE",
12604
+ handout: "HANDOUT",
12605
+ worksheet: "WKS",
12606
+ ext: "EXT",
12607
+ codelab: "CODE",
12608
+ exit_ticket: "EXIT_TICKET"
12609
+ }[artifactType];
12610
+ const gateMode = kitGateType ? gateModeFor(gates, kitGateType) : "OFF";
12611
+ if (gateMode === "OFF") {
12612
+ return { artifactType, filename: meta.filename, content: finalContent, persona: meta.persona, thought: finalThought };
12613
+ }
12614
+ const injectReviewMeta = (doc, metaMap) => {
12615
+ const fm = doc.match(/^---\s*\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
12616
+ if (!fm) {
12617
+ return `---
12618
+ ${Object.entries(metaMap).map(([k, v]) => `${k}: "${v}"`).join("\n")}
12619
+ ---
12620
+
12621
+ ${doc}`;
12622
+ }
12623
+ let yaml = fm[1] ?? "";
12624
+ for (const [k, v] of Object.entries(metaMap)) {
12625
+ const re = new RegExp(`^${k}:.*$`, "m");
12626
+ if (re.test(yaml)) yaml = yaml.replace(re, `${k}: "${v}"`);
12627
+ else yaml += `
12628
+ ${k}: "${v}"`;
12629
+ }
12630
+ return doc.replace(fm[0], `---
12631
+ ${yaml.trim()}
12632
+ ---
12633
+ `);
12592
12634
  };
12635
+ if (gateMode === "HITL") {
12636
+ return {
12637
+ artifactType,
12638
+ filename: meta.filename,
12639
+ content: injectReviewMeta(finalContent, { review_status: "PENDING_REVIEW", review_decision: "PENDING" }),
12640
+ persona: meta.persona,
12641
+ thought: finalThought,
12642
+ pausedForReview: true,
12643
+ gateStatus: "awaiting_approval"
12644
+ };
12645
+ }
12646
+ const judgeObjectives = [{ code: "A1", description: `Artifact fulfills its pedagogical contract for topic "${topic}" with complete required sections`, bloomLevel: "Analyze" }];
12647
+ try {
12648
+ const verdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
12649
+ targetArtifactType: artifactType.toUpperCase(),
12650
+ lessonId: lessonId || "ON_DEMAND",
12651
+ expectedLanguage: language.toLowerCase().includes("viet") ? "vietnamese" : "english",
12652
+ targetObjectives: judgeObjectives,
12653
+ generatedContentJson: JSON.stringify({ content: finalContent, artifactType, lessonId: lessonId || "ON_DEMAND", title: displayTitle })
12654
+ });
12655
+ const passed = Boolean(verdict.passed) && verdict.score >= 85;
12656
+ if (passed) {
12657
+ return {
12658
+ artifactType,
12659
+ filename: meta.filename,
12660
+ content: injectReviewMeta(finalContent, {
12661
+ review_status: "APPROVED",
12662
+ reviewed_by: "@reviewer (LLM-as-Judge)",
12663
+ review_decision: "APPROVED"
12664
+ }),
12665
+ persona: meta.persona,
12666
+ thought: finalThought,
12667
+ judgeScore: verdict.score,
12668
+ judgeCritique: verdict.critique
12669
+ };
12670
+ }
12671
+ const repairFeedback = [verdict.autoRepairInstructions, ...verdict.weaknesses || []].filter(Boolean).join("\n");
12672
+ const repairedRaw = await streamCurriculumAIInference(
12673
+ [
12674
+ { role: "user", content: `You previously authored \`${meta.filename}\` and the academic Judge REJECTED it with the critique below.
12675
+ Rewrite the COMPLETE corrected document: fix every listed issue, keep the mandatory structure, frontmatter and all approved sections. Output 100% clean Markdown only.
12676
+
12677
+ JUDGE CRITIQUE:
12678
+ ${repairFeedback}
12679
+
12680
+ CURRENT DOCUMENT:
12681
+ ${finalContent}` }
12682
+ ],
12683
+ userPrompt,
12684
+ { ...options, systemPersona: systemPrompt },
12685
+ (chunk, type) => {
12686
+ if (onChunk) onChunk(chunk, type === "thought" ? "thought" : "content");
12687
+ }
12688
+ );
12689
+ const repairedExtract = extractThoughtAndContent(repairedRaw);
12690
+ const repaired = repairedExtract.content || repairedRaw;
12691
+ if (repaired && repaired.trim().length > 100) {
12692
+ const reVerdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
12693
+ targetArtifactType: artifactType.toUpperCase(),
12694
+ lessonId: lessonId || "ON_DEMAND",
12695
+ expectedLanguage: language.toLowerCase().includes("viet") ? "vietnamese" : "english",
12696
+ targetObjectives: judgeObjectives,
12697
+ generatedContentJson: JSON.stringify({ content: repaired, artifactType, lessonId: lessonId || "ON_DEMAND", title: displayTitle })
12698
+ });
12699
+ if (reVerdict.passed && reVerdict.score >= 85) {
12700
+ return {
12701
+ artifactType,
12702
+ filename: meta.filename,
12703
+ content: injectReviewMeta(repaired, {
12704
+ review_status: "APPROVED",
12705
+ reviewed_by: "@reviewer (LLM-as-Judge)",
12706
+ review_decision: "APPROVED"
12707
+ }),
12708
+ persona: meta.persona,
12709
+ thought: repairedExtract.thought || "",
12710
+ judgeScore: reVerdict.score,
12711
+ judgeCritique: reVerdict.critique
12712
+ };
12713
+ }
12714
+ return {
12715
+ artifactType,
12716
+ filename: meta.filename,
12717
+ content: injectReviewMeta(repaired, {
12718
+ review_status: "NEEDS_REVISION",
12719
+ reviewed_by: "@reviewer (LLM-as-Judge)",
12720
+ review_decision: "NEEDS_REVISION"
12721
+ }),
12722
+ persona: meta.persona,
12723
+ thought: repairedExtract.thought || "",
12724
+ pausedForReview: true,
12725
+ gateStatus: "judge_needs_revision",
12726
+ judgeScore: reVerdict.score,
12727
+ judgeCritique: reVerdict.critique
12728
+ };
12729
+ }
12730
+ return {
12731
+ artifactType,
12732
+ filename: meta.filename,
12733
+ content: injectReviewMeta(finalContent, {
12734
+ review_status: "NEEDS_REVISION",
12735
+ reviewed_by: "@reviewer (LLM-as-Judge)",
12736
+ review_decision: "NEEDS_REVISION"
12737
+ }),
12738
+ persona: meta.persona,
12739
+ thought: finalThought,
12740
+ pausedForReview: true,
12741
+ gateStatus: "judge_needs_revision",
12742
+ judgeScore: verdict.score,
12743
+ judgeCritique: verdict.critique
12744
+ };
12745
+ } catch (judgeErr) {
12746
+ return {
12747
+ artifactType,
12748
+ filename: meta.filename,
12749
+ content: injectReviewMeta(finalContent, {
12750
+ review_status: "NEEDS_REVISION",
12751
+ review_decision: "NEEDS_REVISION",
12752
+ critique: `Judge unavailable (fail-closed): ${String(judgeErr?.message || judgeErr).slice(0, 300)}`
12753
+ }),
12754
+ persona: meta.persona,
12755
+ thought: finalThought,
12756
+ pausedForReview: true,
12757
+ gateStatus: "judge_error"
12758
+ };
12759
+ }
12593
12760
  } catch (error) {
12594
12761
  throw createAiInferenceError({
12595
12762
  errorCode: "ERR_AI_ALL_PROVIDERS_FAILED",
@@ -13345,43 +13512,15 @@ function safeParseJson(rawText) {
13345
13512
  return null;
13346
13513
  }
13347
13514
  }
13348
- async function readSseStream(reader, decoder, onData) {
13349
- let buffer = "";
13350
- while (true) {
13351
- const { done, value } = await reader.read();
13352
- if (done) break;
13353
- buffer += decoder.decode(value, { stream: true });
13354
- const lines = buffer.split("\n");
13355
- buffer = lines.pop() || "";
13356
- for (const line of lines) {
13357
- const trimmed = line.trim();
13358
- if (!trimmed || trimmed.startsWith(":")) continue;
13359
- if (trimmed === "data: [DONE]") return;
13360
- if (trimmed.startsWith("data: ")) {
13361
- const dataStr = trimmed.slice(6).trim();
13362
- if (dataStr) onData(dataStr);
13363
- }
13364
- }
13365
- }
13366
- }
13367
13515
  async function streamLLMWithFallback(systemPrompt, userPrompt, apiKeys = {}, onChunk) {
13368
- apiKeys.alibaba || apiKeys.dashscope || process.env.ALIBABA_API_KEY || process.env.DASHSCOPE_API_KEY;
13516
+ const alibabaKey = apiKeys.alibaba || apiKeys.dashscope || process.env.ALIBABA_API_KEY || process.env.DASHSCOPE_API_KEY;
13369
13517
  const nvidiaKey = apiKeys.nvidia || process.env.NVIDIA_API_KEY;
13370
- apiKeys.deepseek || process.env.DEEPSEEK_API_KEY;
13518
+ const deepseekKey = apiKeys.deepseek || process.env.DEEPSEEK_API_KEY;
13371
13519
  const openrouterKey = apiKeys.openrouter || process.env.OPENROUTER_API_KEY;
13372
- apiKeys.gemini || process.env.GEMINI_API_KEY;
13520
+ const geminiKey = apiKeys.gemini || process.env.GEMINI_API_KEY;
13373
13521
  const openrouterPreset = process.env.OPENROUTER_FREE_PRESET || "@preset/coding-free";
13374
- const messages = [
13375
- {
13376
- role: "system",
13377
- content: `${systemPrompt}
13378
-
13379
- THINKING DIRECTIVE: Keep reasoning concise, structured, and focused strictly on the core pedagogical trade-offs in 4-6 concise bullet points (under 120 words). Then output the JSON immediately.`
13380
- },
13381
- { role: "user", content: userPrompt }
13382
- ];
13522
+ const candidates = [];
13383
13523
  if (openrouterKey && isProviderEnabled("openrouter")) {
13384
- const t0 = Date.now();
13385
13524
  const orModels = [
13386
13525
  openrouterPreset,
13387
13526
  "openrouter/free",
@@ -13391,174 +13530,82 @@ THINKING DIRECTIVE: Keep reasoning concise, structured, and focused strictly on
13391
13530
  "minimax/minimax-m3:free",
13392
13531
  "cohere/north-mini-code:free"
13393
13532
  ].filter((m) => isModelAllowed(m));
13394
- const uniqueOrModels = Array.from(new Set(orModels));
13395
- for (const model of uniqueOrModels) {
13396
- try {
13397
- const controller = new AbortController();
13398
- const timeout = setTimeout(() => controller.abort(), 25e3);
13399
- const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
13400
- method: "POST",
13401
- headers: {
13402
- "Content-Type": "application/json",
13403
- "Authorization": `Bearer ${openrouterKey}`
13404
- },
13405
- body: JSON.stringify({
13406
- model,
13407
- messages,
13408
- stream: true,
13409
- temperature: 0.3
13410
- }),
13411
- signal: controller.signal
13412
- });
13413
- clearTimeout(timeout);
13414
- if (res.ok && res.body) {
13415
- const reader = res.body.getReader();
13416
- const decoder = new TextDecoder();
13417
- let fullContent = "";
13418
- await readSseStream(reader, decoder, (dataStr) => {
13419
- try {
13420
- const parsed = JSON.parse(dataStr);
13421
- const delta = parsed.choices?.[0]?.delta;
13422
- if (delta?.content) {
13423
- fullContent += delta.content;
13424
- onChunk?.(delta.content, "content");
13425
- }
13426
- } catch {
13427
- }
13428
- });
13429
- if (fullContent.trim()) {
13430
- console.log(`[curriculum-kit:LayerPrefill] \u2705 Tier 1 OpenRouter (${model}) streamed in ${Date.now() - t0}ms`);
13431
- return fullContent.trim();
13432
- }
13433
- }
13434
- } catch (e) {
13435
- console.warn(`[curriculum-kit:LayerPrefill] Tier 1 OpenRouter stream failed for ${model} in ${Date.now() - t0}ms:`, e?.message || e);
13436
- }
13533
+ for (const m of Array.from(new Set(orModels))) {
13534
+ candidates.push({ provider: "openrouter", model: m, apiKey: openrouterKey });
13437
13535
  }
13438
13536
  }
13439
13537
  if (nvidiaKey && isProviderEnabled("nvidia")) {
13440
- const t0 = Date.now();
13441
13538
  const nemotronModels = [
13442
13539
  "nvidia/nemotron-3-ultra-550b-a55b",
13443
13540
  "nvidia/nemotron-3.5-lightning-30b-a3b",
13444
13541
  "nvidia/nemotron-3-super-120b-a12b",
13445
13542
  "nvidia/llama-3.1-nemotron-70b-instruct"
13446
13543
  ].filter((m) => isModelAllowed(m));
13447
- for (const model of nemotronModels) {
13448
- try {
13449
- const controller = new AbortController();
13450
- const timeout = setTimeout(() => controller.abort(), 25e3);
13451
- const res = await fetch("https://integrate.api.nvidia.com/v1/chat/completions", {
13452
- method: "POST",
13453
- headers: {
13454
- "Content-Type": "application/json",
13455
- "Authorization": `Bearer ${nvidiaKey}`
13456
- },
13457
- body: JSON.stringify({
13458
- model,
13459
- messages,
13460
- stream: true,
13461
- temperature: 0.2
13462
- }),
13463
- signal: controller.signal
13464
- });
13465
- clearTimeout(timeout);
13466
- if (res.ok && res.body) {
13467
- const reader = res.body.getReader();
13468
- const decoder = new TextDecoder();
13469
- let fullContent = "";
13470
- await readSseStream(reader, decoder, (dataStr) => {
13471
- try {
13472
- const parsed = JSON.parse(dataStr);
13473
- const delta = parsed.choices?.[0]?.delta;
13474
- if (delta?.content) {
13475
- fullContent += delta.content;
13476
- onChunk?.(delta.content, "content");
13477
- }
13478
- } catch {
13479
- }
13480
- });
13481
- if (fullContent.trim()) {
13482
- console.log(`[curriculum-kit:LayerPrefill] \u2705 Tier 2 NVIDIA NIM (${model}) streamed in ${Date.now() - t0}ms`);
13483
- return fullContent.trim();
13484
- }
13485
- }
13486
- } catch (e) {
13487
- console.warn(`[curriculum-kit:LayerPrefill] Tier 2 NVIDIA NIM stream failed for ${model} in ${Date.now() - t0}ms:`, e?.message || e);
13488
- }
13544
+ for (const m of nemotronModels) {
13545
+ candidates.push({ provider: "nvidia", model: m, apiKey: nvidiaKey });
13546
+ }
13547
+ }
13548
+ if (alibabaKey && isProviderEnabled("alibaba")) {
13549
+ const aliModels = ["qwen-plus", "qwen-turbo", "qwen3.7-plus"].filter((m) => isModelAllowed(m));
13550
+ for (const m of aliModels) {
13551
+ candidates.push({ provider: "alibaba", model: m, apiKey: alibabaKey });
13552
+ }
13553
+ }
13554
+ if (deepseekKey && isProviderEnabled("deepseek")) {
13555
+ const dsModels = ["deepseek-chat", "deepseek-coder"].filter((m) => isModelAllowed(m));
13556
+ for (const m of dsModels) {
13557
+ candidates.push({ provider: "deepseek", model: m, apiKey: deepseekKey });
13558
+ }
13559
+ }
13560
+ if (geminiKey && (isProviderEnabled("gemini") || isProviderEnabled("google"))) {
13561
+ const gModels = ["gemini-1.5-flash", "gemini-2.0-flash", "gemini-1.5-pro"].filter((m) => isModelAllowed(m));
13562
+ for (const m of gModels) {
13563
+ candidates.push({ provider: "google", model: m, apiKey: geminiKey });
13489
13564
  }
13490
13565
  }
13491
13566
  const fallbackChain = getDesignatedFallbackChain();
13492
13567
  for (const target of fallbackChain) {
13493
- const { provider, model } = target;
13494
- if (provider === "nvidia" && nvidiaKey && isProviderEnabled("nvidia")) {
13495
- try {
13496
- const res = await fetch("https://integrate.api.nvidia.com/v1/chat/completions", {
13497
- method: "POST",
13498
- headers: {
13499
- "Content-Type": "application/json",
13500
- "Authorization": `Bearer ${nvidiaKey}`
13501
- },
13502
- body: JSON.stringify({
13503
- model,
13504
- messages,
13505
- stream: true,
13506
- temperature: 0.2
13507
- })
13508
- });
13509
- if (res.ok && res.body) {
13510
- const reader = res.body.getReader();
13511
- const decoder = new TextDecoder();
13512
- let fullContent = "";
13513
- await readSseStream(reader, decoder, (dataStr) => {
13514
- try {
13515
- const parsed = JSON.parse(dataStr);
13516
- const delta = parsed.choices?.[0]?.delta;
13517
- if (delta?.content) {
13518
- fullContent += delta.content;
13519
- onChunk?.(delta.content, "content");
13520
- }
13521
- } catch {
13522
- }
13523
- });
13524
- if (fullContent.trim()) return fullContent.trim();
13568
+ if (!candidates.some((c) => c.provider === target.provider && c.model === target.model)) {
13569
+ candidates.push({
13570
+ provider: target.provider,
13571
+ model: target.model,
13572
+ apiKey: apiKeys[target.provider]
13573
+ });
13574
+ }
13575
+ }
13576
+ const systemInstructions = `${systemPrompt}
13577
+
13578
+ THINKING DIRECTIVE: Keep reasoning concise, structured, and focused strictly on the core pedagogical trade-offs in 4-6 concise bullet points (under 120 words). Then output the JSON immediately.`;
13579
+ for (const candidate of candidates) {
13580
+ const t0 = Date.now();
13581
+ try {
13582
+ const modelInstance = getAIModel({
13583
+ provider: candidate.provider,
13584
+ modelName: candidate.model,
13585
+ apiKey: candidate.apiKey
13586
+ });
13587
+ const streamResult = streamText({
13588
+ model: modelInstance,
13589
+ system: systemInstructions,
13590
+ prompt: userPrompt,
13591
+ temperature: 0.2,
13592
+ abortSignal: AbortSignal.timeout(25e3)
13593
+ });
13594
+ let fullContent = "";
13595
+ for await (const part of streamResult.fullStream) {
13596
+ if (part.type === "reasoning-delta") {
13597
+ onChunk?.(part.text, "thought");
13598
+ } else if (part.type === "text-delta") {
13599
+ fullContent += part.text;
13600
+ onChunk?.(part.text, "content");
13525
13601
  }
13526
- } catch {
13527
13602
  }
13528
- } else if (provider === "openrouter" && openrouterKey && isProviderEnabled("openrouter")) {
13529
- try {
13530
- const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
13531
- method: "POST",
13532
- headers: {
13533
- "Content-Type": "application/json",
13534
- "Authorization": `Bearer ${openrouterKey}`
13535
- },
13536
- body: JSON.stringify({
13537
- model,
13538
- messages,
13539
- stream: true,
13540
- temperature: 0.2
13541
- })
13542
- });
13543
- if (res.ok && res.body) {
13544
- const reader = res.body.getReader();
13545
- const decoder = new TextDecoder();
13546
- let fullContent = "";
13547
- await readSseStream(reader, decoder, (dataStr) => {
13548
- try {
13549
- const parsed = JSON.parse(dataStr);
13550
- const delta = parsed.choices?.[0]?.delta;
13551
- if (delta?.content) {
13552
- fullContent += delta.content;
13553
- onChunk?.(delta.content, "content");
13554
- }
13555
- } catch {
13556
- }
13557
- });
13558
- if (fullContent.trim()) return fullContent.trim();
13559
- }
13560
- } catch {
13603
+ if (fullContent.trim()) {
13604
+ console.log(`[curriculum-kit:VercelAI] \u2705 ${candidate.provider} (${candidate.model}) streamed in ${Date.now() - t0}ms`);
13605
+ return fullContent.trim();
13561
13606
  }
13607
+ } catch (e) {
13608
+ console.warn(`[curriculum-kit:VercelAI] Candidate ${candidate.provider} (${candidate.model}) failed in ${Date.now() - t0}ms:`, e?.message || e);
13562
13609
  }
13563
13610
  }
13564
13611
  return null;
@@ -14726,10 +14773,10 @@ var approvalPayloadSchema = z.object({
14726
14773
  feedback: z.string().optional().describe("Actionable feedback or required changes if rejected"),
14727
14774
  timestamp: z.string().optional().describe("ISO timestamp of the approval action")
14728
14775
  });
14729
- var hookFactory = workflowPkg.defineHook || workflowPkg.createHook || ((opts) => opts);
14730
- var lessonApprovalHook = hookFactory({
14731
- schema: approvalPayloadSchema
14732
- });
14776
+ var lessonApprovalHook = defineHook();
14777
+ function approvalHookToken(projectId, lessonId, artifactType) {
14778
+ return `approval:${projectId}:${lessonId}:${artifactType}`;
14779
+ }
14733
14780
 
14734
14781
  // src/standards/standardsCoverageGate.ts
14735
14782
  function resolveStatementRef(ref, packs) {
@@ -15079,9 +15126,9 @@ async function generateMilestoneWorkflow(input) {
15079
15126
  } else if (lessonGate === "HITL") {
15080
15127
  const hookToken = "gate:lesson:" + milestoneId;
15081
15128
  console.log(" \u23F8 [Gate] LESSON awaiting HUMAN review (HITL) \u2014 hook " + hookToken);
15082
- const workflowPkg2 = await import('workflow');
15083
- const createHook2 = workflowPkg2.createHook;
15084
- const hook = createHook2({ token: hookToken });
15129
+ const workflowPkg = await import('workflow');
15130
+ const createHook = workflowPkg.createHook;
15131
+ const hook = createHook({ token: hookToken });
15085
15132
  const review = await hook;
15086
15133
  console.log(" \u2705 [Gate] Human verdict: " + (review.approved ? "APPROVED" : "REJECTED") + (review.feedback ? " \u2014 " + review.feedback : ""));
15087
15134
  if (!review.approved) {
@@ -15101,7 +15148,7 @@ async function generateMilestoneWorkflow(input) {
15101
15148
  standardsContext: standardsContext || void 0,
15102
15149
  modelOptions: input.modelOptions
15103
15150
  });
15104
- const hook2 = createHook2({ token: hookToken + ":v2" });
15151
+ const hook2 = createHook({ token: hookToken + ":v2" });
15105
15152
  const review2 = await hook2;
15106
15153
  console.log(" \u2705 [Gate] Human verdict (v2): " + (review2.approved ? "APPROVED" : "REJECTED"));
15107
15154
  if (!review2.approved) {
@@ -16711,6 +16758,36 @@ var MediaLedger = class {
16711
16758
  doneCount() {
16712
16759
  return this.listByStatus("done").length;
16713
16760
  }
16761
+ /**
16762
+ * Scan artifact content và seed pending entries cho mọi placeholder [IMAGE: slug].
16763
+ * Được gọi sau khi agent sinh artifact (trước khi Curator duyệt) — đây là cầu nối
16764
+ * duy nhất giữa "agent chèn placeholder" và "sổ cái có entry để Curator/Fulfiller xử".
16765
+ * Idempotent: slug đã có entry active (pending/approved/done) → giữ nguyên;
16766
+ * chỉ re-describe khi entry trước bị rejected/failed.
16767
+ */
16768
+ seedFromArtifact(artifactId, content) {
16769
+ const seeded = [];
16770
+ const re = /\[IMAGE\s*:\s*([a-z0-9][a-z0-9-]*)\s*\]/gi;
16771
+ const seen = /* @__PURE__ */ new Set();
16772
+ let m;
16773
+ while ((m = re.exec(content)) !== null) {
16774
+ const slug = m[1].toLowerCase();
16775
+ if (seen.has(slug)) continue;
16776
+ seen.add(slug);
16777
+ const existing = this.entries.get(slug);
16778
+ const isActive = existing && (existing.status === "pending" || existing.status === "approved" || existing.status === "done");
16779
+ if (isActive) continue;
16780
+ seeded.push(this.upsert({
16781
+ slug,
16782
+ artifactId,
16783
+ name: slug.replace(/^(img-|image-)/, "").replace(/-/g, " "),
16784
+ description: `Placeholder ch\xE8n b\u1EDFi agent trong artifact ${artifactId} \u2014 ch\u1EDD Curator enrich (m\xF4 t\u1EA3 g\u1ED1c ch\u01B0a c\xF3).`,
16785
+ mode: "generate",
16786
+ status: "pending"
16787
+ }));
16788
+ }
16789
+ return seeded;
16790
+ }
16714
16791
  };
16715
16792
 
16716
16793
  // src/media/curator.ts
@@ -16941,6 +17018,6 @@ function renderMediaPlaceholder(entry) {
16941
17018
  return `> \u{1F5BC}\uFE0F [\u1EA2nh \u0111ang ch\u1EDD: ${entry.name} \u2014 s\u1EBD \u0111\u01B0\u1EE3c t\u1EA1o sau khi duy\u1EC7t media]`;
16942
17019
  }
16943
17020
 
16944
- export { ACT_TEMPLATE, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BELL_RINGER_TEMPLATE, BLOOM_ACTION_VERBS, BOM_TEMPLATE, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CHOICE_BOARD_TEMPLATE, CODE_LAB_TEMPLATE, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, EXIT_TICKET_TEMPLATE, EXPOSITION_REL, EXT_TEMPLATE, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GLOSSARY_TEMPLATE, GRAPHIC_ORGANIZER_TEMPLATE, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HANDOUT_TEMPLATE, HandoutSchema, HandoutSectionSchema, InstructionSectionSchema, InstructionStepSchema, JudgeCriterionSchema, LESSON_PLAN_TEMPLATE, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MappingKindSchema, MarpSlideSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PROJECT_INSTRUCTION_TEMPLATE, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QUIZ_TEMPLATE, QualityAuditVerdictSchema, QuizOptionSchema, REVIEW_GAME_TEMPLATE, RUBRIC_TEMPLATE, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SCIENCE_LAB_TEMPLATE, SELF_LAB_TEMPLATE, SLIDE_LAYOUT_PRESETS, SLIDE_TEMPLATE, STANDARD_SOT_FILES, STATION_ROTATION_TEMPLATE, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SilverTierSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TASK_CARDS_TEMPLATE, TEACHER_GUIDE_TEMPLATE, TIERED_PRACTICE_TEMPLATE, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WORKSHEET_TEMPLATE, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, activityTools, analystTools, analyzeProjectCreationIntent, approvalPayloadSchema, assertAcyclic, assessorTools, auditCurriculumQualityFlow, auditQualityReport, buildActivityPrompt, buildCodeLabPrompt, buildCurriculumContext, buildCurriculumPlan, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildExpositionContext, buildExtensionPrompt, buildHandoutPrompt, buildImagePrompt, buildJudgePrompt, buildLessonMasterPrompt, buildProjectInstructionPrompt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWorksheetPrompt, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createCurriculumStorage, curateMediaLedger, designerTools, detectProjectPedagogy, ensureExpositionForLesson, ensureKnowledgeExposition, evaluateStandardsCoverage, executeCurriculumCommand, executeSingleArtifactStep, exportAllProjectQuizzes, expositionCacheKey, extractScopeSequenceRows, extractSessionSlice, extractThoughtAndContent, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateActivityStep, generateCodeLabFlow, generateCodeLabStep, generateDiagnosticQuizFlow, generateDiagnosticQuizStep, generateEducationalImage, generateExtensionFlow, generateExtensionStep, generateHandoutFlow, generateHandoutStep, generateLessonMasterFlow, generateMasterLessonStep, generateMilestoneCurriculumBundle, generateMilestoneWorkflow, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateRoadmapWorkflow, generateSelfLabFlow, generateSelfLabStep, generateSelfPacedBundle, generateSingleArtifact, generateSingleArtifactWorkflow, generateSlidesFlow, generateSlidesStep, generateTeacherGuideFlow, generateTeacherGuideStep, generateWorksheetFlow, generateWorksheetStep, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, judgeMasterLessonStep, judgeSatelliteStep, lessonApprovalHook, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, packagerTools, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToGitStep, publishToSupabase, publishToSupabaseStep, rankGenCandidates, renderFrameworkFromPlan, renderMediaPlaceholder, repairMasterLessonStep, researcherTools, resolveGateSettings, resolveStandardsPacks, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, saveMilestoneToWorkspaceStep, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, techSmeTools, topoSort, uploadAssetToBucket, validateCurriculumPlan, validateFrameworkPack, validateMarkdownTables, validateMermaidSyntax, withAutoRepair, withRateLimitBackoff };
17021
+ export { ACT_TEMPLATE, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BELL_RINGER_TEMPLATE, BLOOM_ACTION_VERBS, BOM_TEMPLATE, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CHOICE_BOARD_TEMPLATE, CODE_LAB_TEMPLATE, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, EXIT_TICKET_TEMPLATE, EXPOSITION_REL, EXT_TEMPLATE, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GLOSSARY_TEMPLATE, GRAPHIC_ORGANIZER_TEMPLATE, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HANDOUT_TEMPLATE, HandoutSchema, HandoutSectionSchema, InstructionSectionSchema, InstructionStepSchema, JudgeCriterionSchema, LESSON_PLAN_TEMPLATE, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MappingKindSchema, MarpSlideSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PROJECT_INSTRUCTION_TEMPLATE, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QUIZ_TEMPLATE, QualityAuditVerdictSchema, QuizOptionSchema, REVIEW_GAME_TEMPLATE, RUBRIC_TEMPLATE, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SCIENCE_LAB_TEMPLATE, SELF_LAB_TEMPLATE, SLIDE_LAYOUT_PRESETS, SLIDE_TEMPLATE, STANDARD_SOT_FILES, STATION_ROTATION_TEMPLATE, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SilverTierSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TASK_CARDS_TEMPLATE, TEACHER_GUIDE_TEMPLATE, TIERED_PRACTICE_TEMPLATE, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WORKSHEET_TEMPLATE, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, activityTools, analystTools, analyzeProjectCreationIntent, approvalHookToken, approvalPayloadSchema, assertAcyclic, assessorTools, auditCurriculumQualityFlow, auditQualityReport, buildActivityPrompt, buildCodeLabPrompt, buildCurriculumContext, buildCurriculumPlan, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildExpositionContext, buildExtensionPrompt, buildHandoutPrompt, buildImagePrompt, buildJudgePrompt, buildLessonMasterPrompt, buildProjectInstructionPrompt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWorksheetPrompt, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createCurriculumStorage, curateMediaLedger, designerTools, detectProjectPedagogy, ensureExpositionForLesson, ensureKnowledgeExposition, evaluateStandardsCoverage, executeCurriculumCommand, executeSingleArtifactStep, exportAllProjectQuizzes, expositionCacheKey, extractScopeSequenceRows, extractSessionSlice, extractThoughtAndContent, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateActivityStep, generateCodeLabFlow, generateCodeLabStep, generateDiagnosticQuizFlow, generateDiagnosticQuizStep, generateEducationalImage, generateExtensionFlow, generateExtensionStep, generateHandoutFlow, generateHandoutStep, generateLessonMasterFlow, generateMasterLessonStep, generateMilestoneCurriculumBundle, generateMilestoneWorkflow, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateRoadmapWorkflow, generateSelfLabFlow, generateSelfLabStep, generateSelfPacedBundle, generateSingleArtifact, generateSingleArtifactWorkflow, generateSlidesFlow, generateSlidesStep, generateTeacherGuideFlow, generateTeacherGuideStep, generateWorksheetFlow, generateWorksheetStep, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, judgeMasterLessonStep, judgeSatelliteStep, lessonApprovalHook, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, packagerTools, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToGitStep, publishToSupabase, publishToSupabaseStep, rankGenCandidates, renderFrameworkFromPlan, renderMediaPlaceholder, repairMasterLessonStep, researcherTools, resolveGateSettings, resolveStandardsPacks, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, saveMilestoneToWorkspaceStep, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, techSmeTools, topoSort, uploadAssetToBucket, validateCurriculumPlan, validateFrameworkPack, validateMarkdownTables, validateMermaidSyntax, withAutoRepair, withRateLimitBackoff };
16945
17022
  //# sourceMappingURL=index.mjs.map
16946
17023
  //# sourceMappingURL=index.mjs.map