@thanh01.pmt/curriculum-kit 1.4.1 → 1.4.2

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.
@@ -1111,7 +1111,9 @@ var LessonPlanSchema = zod.z.object({
1111
1111
  name: zod.z.string().optional().default(""),
1112
1112
  description: zod.z.string(),
1113
1113
  bloomLevel: zod.z.string().default("understand"),
1114
- successCriteria: zod.z.string().optional().default("")
1114
+ successCriteria: zod.z.string().optional().default(""),
1115
+ standardRefs: zod.z.array(zod.z.string()).optional(),
1116
+ conceptRefs: zod.z.array(zod.z.string()).optional()
1115
1117
  })).default([]),
1116
1118
  prerequisites: zod.z.string().optional().default(""),
1117
1119
  materialsSummary: zod.z.string().optional().default(""),
@@ -5634,9 +5636,170 @@ var csta_k12_2017_default = {
5634
5636
  ]
5635
5637
  };
5636
5638
 
5639
+ // src/standards/data/acm-ieee-cs2023.json
5640
+ var acm_ieee_cs2023_default = {
5641
+ manifest: {
5642
+ id: "acm-ieee-cs2023",
5643
+ name: "ACM/IEEE-CS/AAAI Computer Science Curricula 2023 (CS2023)",
5644
+ specVersion: "1.0",
5645
+ contentVersion: "2023.1",
5646
+ subject: "computing",
5647
+ languages: ["en"],
5648
+ gradeModel: {
5649
+ type: "grades",
5650
+ range: [9, 16]
5651
+ },
5652
+ provenance: {
5653
+ sourceRef: "ACM/IEEE-CS/AAAI Computer Science Curricula 2023 - cs2023.org",
5654
+ sourceUrl: "https://cs2023.org",
5655
+ license: "ACM / IEEE Computer Society (cited verbatim for curriculum alignment)",
5656
+ importedBy: "platform",
5657
+ importedAt: "2026-09-11T00:00:00.000Z"
5658
+ },
5659
+ trust: "verified"
5660
+ },
5661
+ statements: [
5662
+ {
5663
+ id: "CS2023-SDF-01",
5664
+ gradeBand: [9, 14],
5665
+ texts: {
5666
+ en: "Design, implement, test, and debug programs using basic computation, standard conditional and iterative structures, and functions."
5667
+ },
5668
+ classifications: [
5669
+ { axis: "Knowledge Area", value: "Software Development Fundamentals (SDF)" },
5670
+ { axis: "Core Tier", value: "Tier-1 Core" }
5671
+ ],
5672
+ bloomHint: { process: "Apply" },
5673
+ keywords: ["algorithms", "control structures", "functions", "variables", "debugging", "programming", "implementation"],
5674
+ sourceRef: "CS2023, Software Development Fundamentals, Program Construction",
5675
+ provenance: { method: "source_official" }
5676
+ },
5677
+ {
5678
+ id: "CS2023-SDF-02",
5679
+ gradeBand: [9, 14],
5680
+ texts: {
5681
+ en: "Apply fundamental data structures (arrays, lists, stacks, queues, hash maps) to represent collections of data and solve algorithmic problems."
5682
+ },
5683
+ classifications: [
5684
+ { axis: "Knowledge Area", value: "Software Development Fundamentals (SDF)" },
5685
+ { axis: "Core Tier", value: "Tier-1 Core" }
5686
+ ],
5687
+ bloomHint: { process: "Apply" },
5688
+ keywords: ["data structures", "arrays", "lists", "hash maps", "collections", "stacks", "queues"],
5689
+ sourceRef: "CS2023, Software Development Fundamentals, Fundamental Data Structures",
5690
+ provenance: { method: "source_official" }
5691
+ },
5692
+ {
5693
+ id: "CS2023-AL-01",
5694
+ gradeBand: [10, 16],
5695
+ texts: {
5696
+ en: "Analyze and compare the time and space complexity of fundamental algorithms using asymptotic notation (Big-O)."
5697
+ },
5698
+ classifications: [
5699
+ { axis: "Knowledge Area", value: "Algorithms and Complexity (AL)" },
5700
+ { axis: "Core Tier", value: "Tier-1 Core" }
5701
+ ],
5702
+ bloomHint: { process: "Analyze" },
5703
+ keywords: ["complexity", "big-o", "efficiency", "sorting", "searching", "asymptotic", "runtime"],
5704
+ sourceRef: "CS2023, Algorithms and Complexity, Basic Analysis",
5705
+ provenance: { method: "source_official" }
5706
+ },
5707
+ {
5708
+ id: "CS2023-SE-01",
5709
+ gradeBand: [9, 16],
5710
+ texts: {
5711
+ en: "Decompose complex problems into modular software components applying principles of abstraction, encapsulation, and separation of concerns."
5712
+ },
5713
+ classifications: [
5714
+ { axis: "Knowledge Area", value: "Software Engineering (SE)" },
5715
+ { axis: "Core Tier", value: "Tier-1 Core" }
5716
+ ],
5717
+ bloomHint: { process: "Create" },
5718
+ keywords: ["modularity", "abstraction", "software design", "refactoring", "encapsulation", "architecture"],
5719
+ sourceRef: "CS2023, Software Engineering, Software Design and Architecture",
5720
+ provenance: { method: "source_official" }
5721
+ },
5722
+ {
5723
+ id: "CS2023-SEC-01",
5724
+ gradeBand: [9, 16],
5725
+ texts: {
5726
+ en: "Incorporate defensive programming and fundamental cybersecurity principles (least privilege, input validation, secure data handling) into software development."
5727
+ },
5728
+ classifications: [
5729
+ { axis: "Knowledge Area", value: "Security (SEC)" },
5730
+ { axis: "Core Tier", value: "Tier-1 Core" }
5731
+ ],
5732
+ bloomHint: { process: "Apply" },
5733
+ keywords: ["security", "defensive programming", "input validation", "cybersecurity", "vulnerabilities"],
5734
+ sourceRef: "CS2023, Security, Secure Software Development",
5735
+ provenance: { method: "source_official" }
5736
+ },
5737
+ {
5738
+ id: "CS2023-AI-01",
5739
+ gradeBand: [10, 16],
5740
+ texts: {
5741
+ en: "Formulate machine learning tasks, prepare training and evaluation datasets, and evaluate model performance using standard metrics."
5742
+ },
5743
+ classifications: [
5744
+ { axis: "Knowledge Area", value: "Artificial Intelligence (AI)" },
5745
+ { axis: "Core Tier", value: "Tier-2 Core" }
5746
+ ],
5747
+ bloomHint: { process: "Evaluate" },
5748
+ keywords: ["artificial intelligence", "machine learning", "dataset", "evaluation", "model", "accuracy"],
5749
+ sourceRef: "CS2023, Artificial Intelligence, Machine Learning Fundamentals",
5750
+ provenance: { method: "source_official" }
5751
+ }
5752
+ ],
5753
+ mappings: [
5754
+ {
5755
+ statementId: "CS2023-SDF-01",
5756
+ targetRef: "ontora:PROGRAM_CONSTRUCTION",
5757
+ kind: "covers",
5758
+ confidence: 0.95,
5759
+ provenance: { method: "source_official" }
5760
+ },
5761
+ {
5762
+ statementId: "CS2023-SDF-02",
5763
+ targetRef: "ontora:DATA_STRUCTURES",
5764
+ kind: "covers",
5765
+ confidence: 0.95,
5766
+ provenance: { method: "source_official" }
5767
+ },
5768
+ {
5769
+ statementId: "CS2023-AL-01",
5770
+ targetRef: "ontora:ALGORITHM_COMPLEXITY",
5771
+ kind: "covers",
5772
+ confidence: 0.95,
5773
+ provenance: { method: "source_official" }
5774
+ },
5775
+ {
5776
+ statementId: "CS2023-SE-01",
5777
+ targetRef: "ontora:SOFTWARE_ARCHITECTURE",
5778
+ kind: "covers",
5779
+ confidence: 0.95,
5780
+ provenance: { method: "source_official" }
5781
+ },
5782
+ {
5783
+ statementId: "CS2023-SEC-01",
5784
+ targetRef: "ontora:DEFENSIVE_PROGRAMMING",
5785
+ kind: "covers",
5786
+ confidence: 0.95,
5787
+ provenance: { method: "source_official" }
5788
+ },
5789
+ {
5790
+ statementId: "CS2023-AI-01",
5791
+ targetRef: "ontora:MACHINE_LEARNING",
5792
+ kind: "covers",
5793
+ confidence: 0.95,
5794
+ provenance: { method: "source_official" }
5795
+ }
5796
+ ]
5797
+ };
5798
+
5637
5799
  // src/standards/bundledPacks.ts
5638
5800
  var BUNDLED_PACK_RECORDS = {
5639
- "csta-k12-2017": csta_k12_2017_default
5801
+ "csta-k12-2017": csta_k12_2017_default,
5802
+ "acm-ieee-cs2023": acm_ieee_cs2023_default
5640
5803
  };
5641
5804
  Object.keys(BUNDLED_PACK_RECORDS).sort();
5642
5805
 
@@ -6243,7 +6406,6 @@ var DEFAULT_KX_PRIORITIES = [
6243
6406
  ];
6244
6407
  function buildSectionAwareExcerpt(markdown, opts = {}) {
6245
6408
  const budget = opts.budget ?? 12e3;
6246
- const minContentChars = opts.minContentChars ?? 400;
6247
6409
  const issues = [];
6248
6410
  const source = (markdown || "").trim();
6249
6411
  if (!source) {
@@ -6256,6 +6418,7 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
6256
6418
  tokenEstimate: 0
6257
6419
  };
6258
6420
  }
6421
+ const minContentChars = opts.minContentChars !== void 0 ? opts.minContentChars : Math.min(400, source.length);
6259
6422
  const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
6260
6423
  const effectiveArtifactType = opts.artifactType || deriveArtifactTypeFromFileName(opts.fileName);
6261
6424
  const sections = parseMarkdownSections(source, slcMap, effectiveArtifactType);
@@ -6275,44 +6438,74 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
6275
6438
  };
6276
6439
  }
6277
6440
  const byCanonical = /* @__PURE__ */ new Map();
6441
+ const byCleanTitle = /* @__PURE__ */ new Map();
6278
6442
  const unmatched = [];
6279
6443
  for (const s of sections) {
6280
6444
  if (s.canonicalKey && !byCanonical.has(s.canonicalKey)) {
6281
6445
  byCanonical.set(s.canonicalKey, s);
6282
- } else {
6446
+ }
6447
+ const norm = normalizeHeading(s.cleanTitle);
6448
+ if (!byCleanTitle.has(norm)) {
6449
+ byCleanTitle.set(norm, s);
6450
+ }
6451
+ if (!s.canonicalKey) {
6283
6452
  unmatched.push(s);
6284
6453
  }
6285
6454
  }
6286
6455
  const priorities = opts.priorities ?? DEFAULT_LESSON_PRIORITIES;
6287
6456
  const includedSections = [];
6288
6457
  const blocks = [];
6289
- let used = 0;
6458
+ const initialOverhead = metaBlock ? metaBlock.length + 2 : 0;
6459
+ let used = initialOverhead;
6290
6460
  const tryAdd = (heading, body, key) => {
6291
6461
  const trimmedBody = body.trim();
6292
6462
  if (!trimmedBody) return false;
6293
6463
  const block = `## ${heading}
6294
6464
 
6295
6465
  ${trimmedBody}`;
6296
- if (used + block.length > budget && used > 0) return false;
6297
- blocks.push(block);
6298
- used += block.length;
6299
- includedSections.push(key);
6300
- return true;
6466
+ if (used + block.length <= budget) {
6467
+ blocks.push(block);
6468
+ used += block.length;
6469
+ includedSections.push(key);
6470
+ return true;
6471
+ }
6472
+ if (includedSections.length === 0 && budget >= minContentChars) {
6473
+ const headingOverhead = `## ${heading}
6474
+
6475
+ `.length;
6476
+ const remaining = budget - used;
6477
+ if (remaining > headingOverhead + 50) {
6478
+ const allowedBody = remaining - headingOverhead;
6479
+ const truncated = truncateByBudget(trimmedBody, allowedBody).trim();
6480
+ if (truncated.length > 0) {
6481
+ const partialBlock = `## ${heading}
6482
+
6483
+ ${truncated}`;
6484
+ blocks.push(partialBlock);
6485
+ used += partialBlock.length;
6486
+ includedSections.push(key);
6487
+ issues.push(`section:truncated:${key}`);
6488
+ return true;
6489
+ }
6490
+ }
6491
+ }
6492
+ return false;
6301
6493
  };
6302
6494
  blocks.push(metaBlock);
6303
6495
  let sectionAware = false;
6304
6496
  for (const key of priorities) {
6305
- const sec = byCanonical.get(key);
6497
+ const sec = byCanonical.get(key) || byCleanTitle.get(normalizeHeading(key));
6306
6498
  if (!sec) continue;
6307
6499
  sectionAware = true;
6308
6500
  if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
6309
6501
  }
6310
6502
  for (const [key, sec] of byCanonical) {
6311
- if (includedSections.includes(key)) continue;
6503
+ if (includedSections.includes(key) || includedSections.includes(sec.cleanTitle)) continue;
6312
6504
  if (used >= budget) break;
6313
6505
  if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
6314
6506
  }
6315
6507
  for (const sec of unmatched) {
6508
+ if (includedSections.includes(sec.cleanTitle)) continue;
6316
6509
  if (used >= budget) break;
6317
6510
  if (!tryAdd(sec.cleanTitle, sec.body, sec.cleanTitle)) break;
6318
6511
  }
@@ -6320,17 +6513,16 @@ ${trimmedBody}`;
6320
6513
  issues.push("parse:no-canonical-resolution");
6321
6514
  }
6322
6515
  if (priorities.length > 0 && !priorities.some((k) => includedSections.includes(k))) {
6323
- issues.push("parse:no-priority-resolution");
6516
+ issues.push(sections.length === 0 ? "parse:no-sections" : "parse:no-priority-resolution");
6324
6517
  }
6325
6518
  let excerpt = blocks.join("\n\n");
6326
6519
  if (excerpt.length > budget) {
6327
6520
  excerpt = truncateByBudget(excerpt, budget);
6328
6521
  }
6329
- const effectiveMinChars = Math.min(minContentChars, source.length);
6330
- if (excerpt.length - metaBlock.length < effectiveMinChars) {
6522
+ if (excerpt.length - metaBlock.length < minContentChars) {
6331
6523
  issues.push("content:insufficient");
6332
6524
  }
6333
- const verified = !issues.includes("parse:no-priority-resolution") && !issues.includes("parse:no-canonical-resolution") && excerpt.length - metaBlock.length >= effectiveMinChars;
6525
+ const verified = !issues.includes("parse:no-priority-resolution") && !issues.includes("parse:no-canonical-resolution") && excerpt.length - metaBlock.length >= minContentChars;
6334
6526
  return {
6335
6527
  excerpt,
6336
6528
  verified,
@@ -6390,7 +6582,7 @@ function parseMarkdownSections(markdown, slcMap, artifactType) {
6390
6582
  }
6391
6583
  }
6392
6584
  const flush = () => {
6393
- if (!currentHeading && currentBody.length === 0) return;
6585
+ if (!currentHeading) return;
6394
6586
  const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
6395
6587
  const norm = normalizeHeading(cleanTitle);
6396
6588
  const canonicalKey = reverseMap.get(norm) || findCanonicalFuzzy(norm);