{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "id": "conan.course-standard",
  "version": "2.2.0",
  "title": "Chuẩn khoá học Conan",
  "description": "Chuẩn mô tả MỘT khoá học gồm những gì, và năm mức hoàn thiện của nó. Phần này là chung cho mọi trường; những gì riêng của một trường nằm ở profile, không nằm ở đây.",
  "shape": {
    "course": {
      "children": "unit",
      "min": 1,
      "requires": [
        "outcomes",
        "learner_fit"
      ],
      "note": "Course Outcome bám thang năng lực (competencyLevels): mỗi outcome là MỘT năng lực ở MỘT mức, kèm bằng chứng nhìn thấy được. learner_fit nói khoá hợp với ai bằng pains / jobs-to-be-done / needs, và cả ai KHÔNG hợp."
    },
    "unit": {
      "children": "lesson",
      "requires": [
        "big_idea",
        "essential_question",
        "purpose",
        "outcomes",
        "key_concepts",
        "misconceptions",
        "prereqs",
        "performance_task"
      ],
      "note": "Các khái niệm trong cùng một unit phải là những khái niệm DỄ NHẦM VỚI NHAU. Nhiệm vụ của unit là giúp phân biệt chúng."
    },
    "lesson": {
      "requires": [
        "guiding_question",
        "outcomes",
        "misconceptions",
        "errors",
        "opening_story",
        "articles",
        "examples",
        "checks",
        "assessment"
      ]
    }
  },
  "levels": [
    {
      "level": 1,
      "key": "frame",
      "title": "Đích đến và người học",
      "answers": "Học xong tôi làm được gì, và khoá này có phải cho tôi không?",
      "artifacts": [
        "unit",
        "lesson",
        "course.outcomes",
        "course.learner_fit"
      ]
    },
    {
      "level": 2,
      "key": "spec",
      "title": "Đặc tả",
      "answers": "Tôi có nên học không, và học xong tôi làm được gì?",
      "artifacts": [
        "unit.big_idea",
        "unit.essential_question",
        "unit.outcomes",
        "unit.misconceptions",
        "unit.performance_task",
        "lesson.outcomes",
        "lesson.misconceptions",
        "lesson.errors"
      ]
    },
    {
      "level": 3,
      "key": "opening",
      "title": "Mở bài",
      "answers": "Vào học thì gặp gì?",
      "artifacts": [
        "unit.opening_story",
        "unit.big_idea_quiz",
        "lesson.guiding_question",
        "lesson.opening_story",
        "lesson.knowledge",
        "lesson.skills"
      ]
    },
    {
      "level": 4,
      "key": "learnable",
      "title": "Học được trọn một vòng",
      "answers": "Tôi học được thật, và đi tiếp được không?",
      "artifacts": [
        "lesson.articles",
        "lesson.examples",
        "lesson.checks",
        "lesson.assessment"
      ]
    },
    {
      "level": 5,
      "key": "assessable",
      "title": "Chấm được sản phẩm",
      "answers": "Làm sao biết tôi đã làm được thật?",
      "artifacts": [
        "unit.performance_task_rubric"
      ]
    }
  ],
  "levelRule": "Một khoá đạt mức N khi MỌI unit và MỌI lesson của nó đủ lớp N. Không lấy trung bình: một khoá mà nửa số bài chưa dạy được thì là mức 3, không phải mức 4 rưỡi. Người học không gặp một khoá trung bình, họ gặp đúng cái bài đang mở.",
  "counts": {
    "note": "Con số mặc định. Trường nào cần khác thì đè bằng profile, KHÔNG sửa file này.",
    "unitsPerCourse": {
      "min": 6,
      "max": 9
    },
    "lessonsPerUnit": {
      "min": 3,
      "max": 5
    },
    "outcomesPerUnit": {
      "min": 2,
      "max": 4
    },
    "misconceptionsPerUnit": {
      "min": 3,
      "max": 4
    },
    "articlesPerLesson": {
      "exact": 3,
      "wordsEach": {
        "min": 100,
        "max": 200
      }
    },
    "examplesPerLesson": {
      "exact": 9,
      "groups": [
        "clear",
        "confusable",
        "nonexample"
      ],
      "perGroup": 3
    },
    "checksPerLesson": {
      "exact": 3,
      "note": "Một câu sau TRỌN mỗi nhóm ví dụ, không phải sau từng ví dụ"
    },
    "assessmentBanks": {
      "formative": 15,
      "summative": 15,
      "note": "Hai ngân hàng KHÔNG giao nhau. 15+15 là đích; dưới 12 mỗi ngân hàng thì lượt sinh coi như hỏng, sinh lại.",
      "minAccept": 12
    },
    "performanceTaskRubric": {
      "criteria": {
        "min": 4,
        "max": 5
      },
      "levelsPerCriterion": 4,
      "weightSum": 1
    },
    "bigIdeaQuizPerUnit": {
      "exact": 10,
      "note": "Trang Unit rút 3 câu ngẫu nhiên mỗi lần tải"
    },
    "courseOutcomes": {
      "min": 3,
      "max": 6,
      "note": "Mỗi outcome một năng lực ở một mức. Nhiều hơn sáu thì không ai nhớ nổi khoá hứa gì."
    },
    "learnerFit": {
      "painsPerCourse": {
        "min": 3,
        "max": 5
      },
      "jobsPerCourse": {
        "min": 3,
        "max": 5
      },
      "needsPerCourse": {
        "min": 3,
        "max": 5
      },
      "notForPerCourse": {
        "min": 2,
        "max": 4
      }
    }
  },
  "gates": {
    "unlockNextUnit": "Làm xong assessment của MỌI bài trong unit trước. Không có ngưỡng điểm.",
    "unitComplete": "Performance Task đạt từ 0.8",
    "note": "Hai cổng cố ý khác nhau: Performance Task không chặn đường đi tiếp, vì việc nặng mà chặn đường thì người ta bỏ giữa chừng. Ngưỡng 0.8 là profile mặc định của Conan School; trường khác đè bằng profile, không sửa chuẩn."
  },
  "qualityRules": [
    {
      "id": "no-leaked-answer",
      "applies": "assessment",
      "rule": "Đề không được chứa nguyên văn đáp án đúng."
    },
    {
      "id": "no-circular",
      "applies": "assessment",
      "rule": "Đáp án đúng không được là một cụm liền nhau nằm trong đề.",
      "seen": "\"Ai là người nghe?\" với đáp án \"Người nghe\""
    },
    {
      "id": "no-shared-stem",
      "applies": "assessment",
      "rule": "Bốn phương án không được cùng mở đầu bằng một đoạn dài giống nhau; phần chung phải nằm ở đề.",
      "seen": "Cả bốn bắt đầu bằng \"Người quyết định là người...\""
    },
    {
      "id": "key-verified",
      "applies": "assessment",
      "rule": "Ô đáp án đúng phải được kiểm lại độc lập. Loại khi người kiểm bất đồng hai lượt liên tiếp và cùng chỉ về một phương án khác.",
      "seen": "Lời giải bênh vực đúng cái đáp án bị chấm sai",
      "verification": {
        "batchSize": 10,
        "crossModel": "Người kiểm phải là MODEL KHÁC với model đã sinh câu hỏi, temperature 0.",
        "twoStrike": "Chỉ loại khi người kiểm bất đồng HAI lượt liên tiếp và cả hai lượt cùng chỉ về một phương án khác."
      }
    },
    {
      "id": "example-no-label",
      "applies": "lesson.examples",
      "rule": "Thân ví dụ không được gọi tên khái niệm hay dán nhãn phân loại; mọi lời phân loại nằm ở ghi chú."
    },
    {
      "id": "story-no-retell",
      "applies": "opening_story",
      "rule": "Lời giải và nút thắt không được kể lại tình huống."
    },
    {
      "id": "story-has-pivot",
      "applies": "opening_story",
      "rule": "Lời giải phải có khoảnh khắc nhân vật đổi cách làm."
    },
    {
      "id": "outcome-observable",
      "applies": "outcomes",
      "rule": "Outcome phải quan sát được. Cấm các cụm rỗng nghĩa trong bannedPhrases.",
      "bannedPhrases": [
        "hiểu rõ hơn",
        "tránh được những hiểu lầm",
        "tránh được hiểu lầm",
        "nắm được kiến thức",
        "hiểu biết về",
        "nâng cao khả năng"
      ]
    },
    {
      "id": "product-countable",
      "applies": "performance_task",
      "rule": "Sản phẩm nộp phải đếm được. Cấm đo bằng số trang."
    },
    {
      "id": "example-no-json",
      "applies": "lesson.examples",
      "rule": "Thân và ghi chú ví dụ không được lẫn mảnh cấu trúc dữ liệu (JSON, key/value).",
      "seen": "...giao hàng.', 'note': 'Đoạn văn này chỉ mô tả...'}, {"
    },
    {
      "id": "article-length",
      "applies": "lesson.articles",
      "rule": "Bài viết 80-240 âm tiết (tương đương 100-200 từ; tiếng Việt tách theo âm tiết nên ngưỡng đo bằng âm tiết phải nới hơn ngưỡng nói bằng từ)."
    },
    {
      "id": "no-foreign-chars",
      "applies": "mọi nội dung hiển thị",
      "rule": "Không lẫn ký tự Hán/Nhật/Hàn giữa câu tiếng Việt.",
      "seen": "Model distill từ Qwen thỉnh thoảng rớt một ký tự Trung vào giữa câu"
    },
    {
      "id": "bank-missing-summative",
      "applies": "assessment",
      "rule": "Bài có ngân hàng formative thì BẮT BUỘC có ngân hàng summative, quiz chốt là thứ mở Unit sau."
    },
    {
      "id": "suspect-answer-key",
      "applies": "assessment",
      "rule": "Câu hỏi mà đa số người học thật (>=5 lượt, >60%) cùng chọn MỘT phương án khác ô đáp án là câu nghi đánh dấu nhầm, dữ liệu người học là lớp kiểm cuối cùng.",
      "seen": "Đáp án bị đánh dấu nhầm lọt qua lượt kiểm hai-lần của chính model ra đề"
    },
    {
      "id": "foreign-term-borrowed",
      "applies": "lesson.articles, lesson.examples",
      "rule": "Nội dung một khoá không dùng thuật ngữ tiếng Anh mà khoá KHÁC sở hữu (foreign_terms trong course_metadata), hàng rào chống trôi chủ đề."
    },
    {
      "id": "outcome-has-level",
      "applies": "course.outcomes",
      "rule": "Mỗi Course Outcome phải gắn đúng một mức trong competencyLevels và kèm bằng chứng nhìn thấy được."
    },
    {
      "id": "learner-fit-has-not-for",
      "applies": "course.learner_fit",
      "rule": "Phải nói cả khoá này KHÔNG hợp với ai. Chỉ nói hợp với ai thì mọi khoá đều hợp với mọi người."
    }
  ],
  "profileFields": {
    "note": "Những gì KHÁC NHAU giữa các trường. Đặt ở profile riêng, không đặt trong chuẩn.",
    "fields": [
      "language",
      "voice",
      "castNames",
      "castScenes",
      "counts",
      "terminology"
    ]
  },
  "levelNote": "Ngân hàng câu hỏi nằm ở mức 4 chứ không phải mức 5: quiz chốt bài là thứ MỞ UNIT SAU. Thiếu nó thì người học đọc hết bài rồi kẹt lại, tức khoá chưa đi hết được một vòng. Mức 5 dành cho việc chấm SẢN PHẨM người học làm ra, là một tầng khác hẳn.",
  "changes": {
    "from": "2.1.0",
    "note": "Mức 1 đổi nghĩa: từ \"có unit và khái niệm\" thành \"có đích đến và chân dung người học\". Thêm competencyLevels (thang bốn mức) mà mọi Course Outcome phải bám vào, và learner_fit (pains / jobs / needs / không hợp với ai). Đây là đổi NGHĨA của một mức nên ra bản mới, v2.1 giữ nguyên tại chỗ."
  },
  "competencyLevels": [
    {
      "key": "aware",
      "level": 1,
      "title": "Nhận ra",
      "means": "Gọi tên được và nhận ra khi gặp, nhưng chưa tự làm."
    },
    {
      "key": "guided",
      "level": 2,
      "title": "Làm được khi có mẫu",
      "means": "Làm đúng khi có khuôn, có ví dụ hoặc có người soát lại."
    },
    {
      "key": "fluent",
      "level": 3,
      "title": "Tự làm được",
      "means": "Tự làm trong việc thật của mình, không cần ai soát."
    },
    {
      "key": "lead",
      "level": 4,
      "title": "Sửa được cho người khác",
      "means": "Nhìn bài người khác chỉ ra chỗ hỏng và nói được vì sao."
    }
  ],
  "competencyNote": "Course Outcome PHẢI gắn một mức trong thang này. Không gắn mức thì \"học xong làm được X\" không kiểm được: làm được ở mức nhận ra khác hẳn làm được ở mức tự làm, mà cùng một câu chữ."
}