Skip to content
Back to skills

Quiz Generator

ASecurity

高校教师出题与测评辅助:按知识点清单规划题量、命制八种题型、生成 A/B 卷、输出双向细目表与复习闪卡,并把题目打包交给 exam-pipeline 做审卷与考后分析。当教师说「出一套题」「编几道练习题」「随堂小测」「帮我出 A/B 卷」「这个知识点出三道题」「期末试卷命题」「给我一份双向细目表」「把题做成能复习的题库」时使用。产出的是**待审题目初稿**,全部题目必须经教师逐题审核后才能进考场。Triggers: 出一套题、编几道练习题、随堂小测、出 A/B 卷、期末命题、单元测验、补考卷、练习题、题库、双向细目表、细目表、闪卡、复习卡、考点覆盖、题量分配、选择题干扰项、判断题、计算题、案例分析题、论述题。

  • 11 stars
  • 0 votes
  • 1 copy
  • 1 view
  • Added October 20, 2026
educationpythongobashgit

Security analysis

A100/100

Scanned October 20, 2026

npx -y skills add EtherealMingo/university-teacher-skills --skill quiz-generator --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Quiz Generator?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Quiz Generator
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/etherealmingo-quiz-generator/badge)](https://www.skillsdirectory.com/skills/etherealmingo-quiz-generator)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: quiz-generator
description: "高校教师出题与测评辅助:按知识点清单规划题量、命制八种题型、生成 A/B 卷、输出双向细目表与复习闪卡,并把题目打包交给 exam-pipeline 做审卷与考后分析。当教师说「出一套题」「编几道练习题」「随堂小测」「帮我出 A/B 卷」「这个知识点出三道题」「期末试卷命题」「给我一份双向细目表」「把题做成能复习的题库」时使用。产出的是**待审题目初稿**,全部题目必须经教师逐题审核后才能进考场。Triggers: 出一套题、编几道练习题、随堂小测、出 A/B 卷、期末命题、单元测验、补考卷、练习题、题库、双向细目表、细目表、闪卡、复习卡、考点覆盖、题量分配、选择题干扰项、判断题、计算题、案例分析题、论述题。"
---

# 出题与测评(quiz-generator)

> **Goal**:把教师的「教学大纲 / 章节知识点 / 一份教材材料」变成一套**结构可查、覆盖可证、难度可控**的试卷与题库初稿——
> 每道题都标好了「考哪个知识点、什么题型、什么认知层次、预计多难、几分」,
> 并输出双向细目表与 A/B 卷等价性校验结果。
> **出的题一律是待审稿,不是终稿**:进考场前必须由教师逐题过一遍。

## 何时使用

- 「出一套题」「期末试卷命题」「帮我出一份期中卷」
- 「编几道练习题」「这个知识点给我出三道题」(题库/作业/练习用)
- 「随堂小测」「课前测」「课后测」(3–5 题,5 分钟量级)
- 「帮我出 A/B 卷」「要两套难度一样的」「补考卷」
- 「给我一份双向细目表」「考点覆盖情况怎么样」「题量怎么分配」
- 「这套题的难度配比对吗」「选择题干扰项再想想」
- 「把这些题做成能反复复习的题库 / 闪卡」

**不适用**(走别的技能):

| 教师想干的事 | 该走 |
|---|---|
| 已经有试卷,要审卷、出评分细则、考后成绩分析、归档 | `exam-pipeline`(本技能**下游**,见「交接协议」) |
| 只是课堂上现场提问、要一条递进提问链、把互动记录算平时分 | `classroom-live` |
| 要教案、课件、教学设计 | `lesson-plan` / `lecture-slides` |
| 要的是课程知识结构图、术语表、FAQ | `learning-graph-generator` / `glossary-generator` / `faq-generator`(均为本包 `skills/` 下的底座技能) |

## 底座(禁止重写)

引用前已 `ls` 验证存在。

| 路径 | 用途 | 本技能怎么用 |
|---|---|---|
| `skills/ibook-skills/question-writing/SKILL.md` | **出题主干方法**:布鲁姆分布分档、概念优先级(Priority 1/2/3)、答案位置均衡、每题必带解析、题目 JSON 结构、质量评分与校验 10 条 | 直接照搬其**方法论与数据结构**,产出物换成中文试卷与 xlsx |
| `skills/ibook-skills/question-writing/references/distractor-writing-guide.md` | **干扰项写作指南**:四个质量维度(可信/有教学价值/能区分/公平)、四类误解型干扰项、四种构造法(相关概念/部分定义/程度差异/时序错位)、0–1 干扰项质量分、按布鲁姆层级举例、修订策略 | 阶段三写选择题时逐条对照,红线级引用 |
| `skills/ibook-skills/learning-graph-generator/` | 知识点依赖图生成,含 CIS(概念影响力)计算与 `validate-learning-graph.py` / `analyze-graph.py` | 教师给的是整门课大纲时,先用它把知识点抽成带依赖的清单,再据此分配题量 |
| `skills/ibook-skills/course-description-analyzer/` | 课程描述完整性校验 + **布鲁姆学习成果**抽取 | 阶段一抽取认知层次目标的依据 |
| `skills/ibook-skills/glossary-generator/SKILL.md` | ISO 11179 式术语定义(精确、简洁、非循环) | 名词解释、术语配对题、填空题答案的唯一性判据 |
| `skills/ibook-skills/faq-generator/` | 教材问答对 + 分类分级导出 JSON | 复习型题库的题干改写来源之一 |
| `skills/learning-education/study-skill/references/fsrs-spaced-repetition.md` | **FSRS 间隔重复协议**:D/S/R 三值、1–4 评分、`add`/`schedule`/`review`/`status` 命令、卡片存储路径、每次复习上限 3 条的混合复习模型 | 阶段七「题目转闪卡」直接按此协议执行 |
| `skills/learning-education/study-skill/scripts/fsrs/` | FSRS 调度器 **Go 源码**(`add/schedule/review/status`,输出 JSON)。⚠️ 仓库不含编译产物,需 Go ≥1.22 自行 `go build`;无 Go 时走阶段七的降级方案 | 闪卡排程 |
| `skills/learning-education/thinking-toolkit/methods/01-socratic-inquiry.md` | 苏格拉底式追问:区分「事实 / 解释 / 价值判断 / 目标」,只问能改变结论的问题,最多 6 问 | 论述题、案例分析题的**小问链**设计(由浅入深逐问逼出论证) |
| `skills/education-skills/edu-learning-analytics/references/competency-based-assessment.md` | **双向细目表**范式(认知层次 × 内容维度 × 建议比例)、素养导向题型分类(情境选择题 / 非连续文本题 / 探究实作题 / 议题讨论题 / 跨领域整合题) | 阶段二细目表与情境题命制的结构模板 |
| `skills/education-skills/edu-learning-analytics/references/peer-assessment.md` | 评分规准(Rubric)设计、评量者训练与标竿范例 | 阶段六评分要点的结构(但完整 rubric 归 `exam-pipeline`) |
| `skills/k12-teacher-skills/k12-check-for-understanding/SKILL.md` | **理解性检查(CFU)**:1–3 个精准形成性题目,干扰项**必须来自有据可查的学生常见错误**;「学生回答 → 下一步教学动作」的教师指引;学生版/教师版分离 | 随堂小测与「教学前摸底题」的命制纪律;干扰项来源的取证要求 |
| `skills/k12-teacher-skills/k12-check-for-understanding/references/verification.md` | 交付前验证协议 | 阶段四质量门的分层校验思路 |
| `skills/office-layer/` | **文件产出唯一通道**:`scripts/docx_kit.py`(`md` / `spec` / `comment` / `inspect`)、`scripts/xlsx_kit.py`(`build` / `analyze` / `inspect`)、`bootstrap.sh` | 试卷 docx、细目表 xlsx、审核批注 |

**许可证注意**:`question-writing` 等 ibook 系列底座的上游仓库**无 LICENSE 文件**(见 `THIRD_PARTY_NOTICES.md`),依法默认保留全部权利。
因此本技能**只借鉴其方法论思路,不整段复制其英文原文、模板文本或代码**进任何交付物;交付物一律用中文重写。

**环境准备**(`.venv` 尚未创建时):

```bash
bash skills/office-layer/bootstrap.sh
PY="skills/office-layer/.venv/bin/python"
export MPLCONFIGDIR=/tmp/mplcache && mkdir -p /tmp/mplcache   # 受限环境必需
```

## 前置信息收集(intake,一次性问完)

**一次性问完,不要边做边问。** 把下面 13 项合并成**一个**问题批次(沿用 `awesome-benzi` 的 `question-batch` 思路)抛给教师。
信息不全时**用下表安全默认值继续**,并在交付说明里逐条标出「本次用了默认值」。

| # | 要问的 | 为什么必须问 | 缺省时怎么走 |
|---|---|---|---|
| 1 | **学科**(以及是否含计算/编程/实验操作) | 决定题型可行域(文科少计算题,工科多计算与设计题) | 从材料自动判定,标注「按材料推断为 X 学科」 |
| 2 | **课程名**(+课程代码、学分、学时) | 试卷卷头与细目表表头 | 用材料中的课程名;无则 `【待补:课程名】` |
| 3 | **知识点范围**:给大纲 / 给教材目录 / 给章节号 / 给已写好的知识点清单 | 这是出题的**唯一依据**,本技能不自己发明考点 | 无大纲时:从教师给的材料逐节抽取,抽完**回读给教师确认**后才出题 |
| 4 | **题量**:总题数,或「总分 + 各题型分值」 | 决定细目表格数与每题配分 | 随堂小测 3–5 题;单元测 15–20 题;期末 25–35 题 |
| 5 | **题型要求**:哪几种题型、各占多少分 | 题型与认知层次强相关(见「题型设计参考」) | 按用途默认(见 §题型设计参考 末尾的「按用途默认配比」) |
| 6 | **难度要求**:目标平均分、易中难比例、是否要有压轴题 | 决定难度预估与分值匹配 | 易:中:难 = 3:5:2;目标平均分默认 75±5(客观题为主卷型);主观题分值占比 >40% 时改按 65±5,见「命题质量原则 §4」卷型口径 |
| 7 | **认知层次要求**:是否按布鲁姆比例、有无上限(如「低年级不要出创造层」) | 决定层次分布硬约束 | 识记 20% / 理解 30% / 应用 30% / 分析 20% |
| 8 | **学生层次**:本科低年级 / 本科高年级 / 研究生 / 专升本 / 留学生(中文授课)/ 高职 | 决定语言难度、情境复杂度、题干的默认知识假设 | 按「本科高年级」走,并在交付说明标注 |
| 9 | **是否要 A/B 卷**(几套、是否需要选项乱序、是否需要答题卡) | 决定是否走阶段五的双卷生成与等价性校验 | 默认**不出** A/B 卷(教师没要求就不加工作量);若为期末考试则**主动提醒**是否需要 |
| 10 | **用途与场合**:随堂小测 / 单元测 / 期中 / 期末 / 补考 / 作业练习 / 长期题库 | 决定正式度、题型配比、是否要密封线与答题卡 | 默认「作业练习卷」 |
| 11 | **考试时长与允许工具**:分钟数、闭卷/开卷、可否用计算器/公式表 | 决定计算题数据是否「算得完」、论述题小问个数 | 默认 120 分钟、闭卷、不允许计算器 |
| 12 | **学校/学院格式要求**:试卷头模板、密封线、得分栏、页眉页脚、A3/A4 双面 | 决定 docx 排版方式(`md` 还是 `spec`) | 用通用卷头(见产出物一节),标注「结构为通用模板,请对照贵校教务处模板调整」 |
| 13 | **产出物要哪些**:试卷 docx / 参考答案 docx / 细目表 xlsx / 题库 JSON / 闪卡包 / 是否要一并交 `exam-pipeline` | 决定交付清单 | 默认交付「试卷 docx + 参考答案 docx + 双向细目表 xlsx + 题库 JSON」 |

> **重要纪律**:第 3 项和第 13 项**不能靠猜**。知识点范围若完全拿不到,只做「从材料抽知识点 → 回读确认」这一步就停,
> 不要凭空造考点——高校正式考试编造考点是教学事故。

## 工作流

每一阶段都写明 **输入 → 动作 → 输出 → 退出条件**。前一阶段退出条件不满足,不进下一阶段。

### 阶段〇 · 环境与底座校验

- **输入**:无。
- **动作**:
  1. `ls skills/office-layer/scripts/` 与 `ls skills/office-layer/.venv/bin/python`,确认产出通道可用;缺 `.venv` 先跑 `bootstrap.sh`。
  2. `ls skills/ibook-skills/question-writing/references/`,确认干扰项指南在位。
  3. 建工作目录 `quiz-<课程名简写>-<日期>/`,过程文件全放这里。
- **输出**:可用环境 + 工作目录。
- **退出条件**:`docx_kit.py`、`xlsx_kit.py` 存在;`skills/office-layer/.venv/bin/python` 可执行(`--help` 有输出)。

### 阶段一 · 知识点清单化

- **输入**:教师给的大纲 / 目录 / 章节材料(intake 第 3 项)。
- **动作**:
  1. 优先顺序:**现成知识点清单 > 教学大纲章节条目 > 教材目录 > 教师给的材料正文**。逐级降级时必须说明依据来源。
  2. 按 `learning-graph-generator` 的思路建**依赖关系**(哪个知识点是哪个的前置),只在教师给了整门课范围时才做全图;单章出题只列同层知识点即可。
  3. 给每个知识点打**重要度**,供阶段二分配题量:

     | 级别 | 判据 | 建议配题权重 |
     |---|---|---|
     | A 核心 | 出现在课程目标/章节标题/考纲「掌握」条目;是其他知识点的前置 | 3 |
     | B 支撑 | 有独立小节、有例题、有术语定义 | 2 |
     | C 了解 | 只在引言/扩展/史料中出现,属于背景 | 1(也可只出 0–1 题或不考) |

  4. 输出 `知识点清单.xlsx`:`编号 | 知识点 | 所属章节 | 重要度 | 前置知识点 | 对应的学习成果(布鲁姆层次)`。
  5. **回读给教师确认**,明确问一句「有没有漏掉的必考点,有没有我列进来但你不打算考的」。
- **输出**:`知识点清单.xlsx`(含 20–80 条不等的知识点行)。
- **退出条件**:教师确认知识点清单;清单里每一条都能指向材料中的具体位置(章节号/页码/小节名)。

### 阶段二 · 题量规划与双向细目表

- **输入**:确认后的 `知识点清单.xlsx`、intake 第 4/5/6/7 项。
- **动作**:
  1. **总题量 → 各知识点配题数**,按权重分摊并做整数化:

     ```
     某知识点配题数 = 总题量 × (该知识点权重 / 全部权重之和)
     A 级知识点:四舍五入后若为 0,强制提到 1 题(核心考点不许 0 题)
     C 级知识点:四舍五入后可保留 0 题(了解性内容不必占分)
     ```

  2. **按认知层次分摊**:把每个知识点的题数再分到布鲁姆层次上,命中 intake 第 7 项的目标比例(默认 识记 20% / 理解 30% / 应用 30% / 分析 20%),允许 ±5 个百分点。
     低年级课程可把「分析」降到 10%,把余量给「理解」。
  3. **按题型落格**:每个「知识点 × 层次」格子选一个合适题型(选型规则见「题型设计参考」);
     **同一份正式试卷里,同一知识点不要在完全相同的层次上重复出同型题**(补考/题库除外)。
  4. **配分**:用「认知层次基准分 × 作答时长系数」定分(见「命题质量原则 §4」),全卷合计必须精确等于总分。
  5. 生成**双向细目表**(阶段产出物 `双向细目表.xlsx`),两个维度:纵轴知识点、横轴题型×认知层次,
     每格填「题号 / 题数 / 分值」,并在右侧出小计与占比。示例:

     | 知识点 | 重要度 | 单选(识记) | 单选(理解) | 多选(应用) | 填空(识记) | 计算(应用) | 简答(分析) | 合计题数 | 合计分值 | 占比 |
     |---|---|---|---|---|---|---|---|---|---|---|
     | 牛顿第一定律 | A | Q1 / 1 / 2 | | | Q6 / 1 / 2 | | | 2 | 4 | 4% |
     | 牛顿第二定律 | A | | Q2 / 1 / 3 | Q8 / 1 / 4 | | Q12 / 1 / 12 | | 3 | 19 | 19% |
     | 动量守恒 | A | | | | | Q13 / 1 / 12 | Q18 / 1 / 10 | 2 | 22 | 22% |
     | 角动量守恒 | C | | Q3 / 1 / 3 | | | | | 1 | 3 | 3% |

  6. 校验三条硬约束,不满足就回到第 1 步重排:
     - **每格都有题**:正式试卷里「某知识点在认知层次 X 上应该有题但细目表格子为空」要显式说明理由。
     - **总分吻合**:各格分值之和 = 卷面总分。
     - **层次比例吻合**:层次占比与目标偏差 ≤ 5pp。
- **输出**:`双向细目表.xlsx`(同一文件内另含「题型分布」「层次分布」「难度预估」「答案位置校验」四个工作表)。
- **退出条件**:三条硬约束全过;细目表打印/导出后可读,教师能一眼看出「哪个考点占了多少分」。

### 阶段三 · 逐题命制

- **输入**:`双向细目表.xlsx`(每一格就是要出的一道或几道题的规格)、知识点对应材料。
- **动作**:
  1. **逐格出题,不跳格**。每道题先写内部字段(这是后面所有校验与交接的数据基础):

     ```json
     {
       "id": "Q07",
       "kp": "牛顿第二定律",
       "kp_level": "A",
       "type": "计算",
       "bloom": "应用",
       "score": 12,
       "est_difficulty": 0.65,
       "stem": "题干全文",
       "options": {"A": "…", "B": "…", "C": "…", "D": "…"},
       "answer": "B",
       "explanation": "为什么这个是答案,其他项错在哪",
       "scoring_points": ["正确写出受力分析式(4 分)", "代入数值并解出 a=2 m/s²(5 分)", "单位与方向正确(3 分)"],
       "source": "教材第 3 章 §3.2 / 教师提供的讲义 p.12",
       "material_sentences": ["用于出题的材料原句(内部留档,不写进试卷)"],
       "common_misconceptions": ["把合力当某一个力", "忘记方向的正负号"],
       "distractor_quality": 0.85,
       "review_status": "待教师审核"
     }
     ```

  2. **选择题/判断题的干扰项,逐项对照 `distractor-writing-guide.md`**:
     干扰项必须能说出「它对应哪一条学生常见错误」,说不出来就重写(见「命题质量原则 §1」)。
  3. **情境题按 `competency-based-assessment.md` 的五类题式选型**:情境选择题 / 非连续文本题(图表判读)/ 探究实作题 / 议题讨论题 / 跨领域整合题。
  4. **主观题的小问链按苏格拉底式追问思路设计**:小问要能区分「事实、解释、价值判断、目标」,
     前一问的答案必须被后一问用到,禁止「(1) 写出定义 (2) 谈谈你的看法」这种互不相干的小问。
  5. 每题写完立刻回填细目表实际信息(题号、实际难度预估),**不要等全卷写完再补**。
  6. 写解析:说明正确项为什么对、每个干扰项错在哪、对应哪个知识点。解析同时是**讲评素材**,别写成「正确答案是 B」。
- **输出**:`题库.json`(全部题目内部字段)+ 每题对应的 `试卷草稿.md` 片段。
- **退出条件**:细目表每一格都有对应题目;每题的 `stem / answer / explanation / scoring_points / source` 字段非空;
  `source` 能指向教师提供的具体材料位置(指不到就留 `【待补:依据出处】`)。

### 阶段四 · 质量门自检

- **输入**:`题库.json`。
- **动作**:
**第 1 步 · 跑自动检查**。把下面这段脚本**原样**存成工作目录里的 `quiz_audit.py`(仅用标准库,不需要 venv;**顶格保存,不要带缩进**),然后按下面的命令行运行。它会输出题型/层次/答案位置分布与层次偏差、题干重复与雷同、**正确项比干扰项明显长**、**用了「以上都不对」凑数**、知识点未覆盖清单:

```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""quiz_audit.py — 出题质量门自检(仅标准库)
用法: python3 quiz_audit.py 题库.json [识记:20,理解:30,应用:30,分析:20] [知识点清单.txt]
"""
import json, re, sys, collections

def norm(s):
    return re.sub(r"[\s,。、;:?!,.;:?!()()【】\[\]「」\"'']+", "", str(s or ""))

def main():
    if len(sys.argv) < 2:
        sys.exit("用法: python3 quiz_audit.py 题库.json [识记:20,理解:30,...] [知识点清单.txt]")
    qs = json.load(open(sys.argv[1], encoding="utf-8"))["questions"]
    target = {}
    if len(sys.argv) > 2 and sys.argv[2].strip():
        for kv in sys.argv[2].split(","):
            if ":" in kv:
                k, v = kv.split(":", 1)
                target[k.strip()] = float(v)
    n = len(qs)
    if not n:
        sys.exit("题库为空")
    print(f"题量 {n} 题|总分 {sum(float(q.get('score') or 0) for q in qs):g} 分")

    for field, label in (("type", "题型"), ("bloom", "认知层次"), ("answer", "答案位置"), ("kp", "知识点")):
        cnt = collections.Counter(str(q.get(field) or "(空)") for q in qs)
        print(f"\n[{label}] {len(cnt)} 类")
        for k, v in cnt.most_common():
            pct = v * 100.0 / n
            line = f"  {k}: {v} 题 ({pct:.0f}%)"
            if field == "bloom" and k in target:
                d = pct - target[k]
                line += f"|目标 {target[k]:.0f}%|偏差 {d:+.0f}pp {'OK' if abs(d) <= 5 else '<<超差'}"
            print(line)

    seen, seen12, flagged = {}, {}, []
    for q in qs:
        stem = norm(q.get("stem"))
        if not stem:
            flagged.append((q.get("id"), "题干为空"))
            continue
        if stem in seen:
            flagged.append((q.get("id"), f"题干与 {seen[stem]} 完全重复"))
        else:
            seen[stem] = q.get("id")
        p12 = stem[:12]
        if p12 in seen12:
            flagged.append((q.get("id"), f"题干前 12 字与 {seen12[p12]} 雷同"))
        else:
            seen12[p12] = q.get("id")

    for q in qs:
        opts, ans = q.get("options") or {}, q.get("answer")
        if not isinstance(opts, dict) or ans not in opts or len(opts) < 3:
            continue
        lens = {k: len(str(v)) for k, v in opts.items()}
        others = [v for k, v in lens.items() if k != ans]
        avg = sum(others) / len(others)
        if avg > 0 and lens[ans] > avg * 1.4:
            flagged.append((q.get("id"),
                f"正确项长度 {lens[ans]} 字,为干扰项均值 {avg:.1f} 的 {lens[ans]/avg:.1f} 倍,答案可能被长度泄露"))
        if any("以上都对" in str(v) or "以上都不对" in str(v) for v in opts.values()):
            flagged.append((q.get("id"), "使用了「以上都对/都不对」凑数选项"))

    if len(sys.argv) > 3:
        plan = [l.strip() for l in open(sys.argv[3], encoding="utf-8") if l.strip() and not l.startswith("#")]
        tested = {norm(q.get("kp")) for q in qs}
        miss = [p for p in plan if norm(p) not in tested]
        cov = (len(plan) - len(miss)) * 100.0 / len(plan)
        print(f"\n[知识点覆盖] 计划 {len(plan)} 个|已覆盖 {len(plan)-len(miss)} 个|覆盖率 {cov:.0f}%")
        for m in miss:
            print(f"  未覆盖: {m}")

    print(f"\n[问题清单] {len(flagged)} 条")
    for qid, msg in flagged:
        print(f"  {qid}: {msg}")
    print("\n结论: " + ("通过(0 条问题)" if not flagged else "未通过,逐条修正后重跑"))

main()
```

跑法(知识点清单每行一个知识点):

```bash
printf '牛顿第一定律\n牛顿第二定律\n动量守恒\n' > 知识点清单.txt
python3 quiz_audit.py 题库.json "识记:20,理解:30,应用:30,分析:20" 知识点清单.txt
```

脚本会报出:题型/层次/答案位置分布与层次偏差、题干重复与雷同、**正确项比干扰项明显长**、
**用了「以上都不对」凑数**、知识点未覆盖清单。

**第 2 步 · 人工过「命题缺陷十查」**(脚本查不出的部分,必须逐条看,见「命题质量原则 §2」):
否定式题干、题干暗示、语法不平行、绝对化词、选项互相包含、「下列哪项**不**属于」、
答案可在题干或别题中找到、主观题分值与小问数不匹配、开卷题在闭卷卷里、跨知识点串题导致两处给分。
**第 3 步 · 读回结构核对**:`docx_kit.py inspect` / `xlsx_kit.py inspect`(交付前必做,见阶段八)。
- **输出**:`出题自检报告.md`(脚本原始输出 + 人工十查的逐条结论 + 每条问题的处理动作)。
- **退出条件**:脚本「问题清单」为 0 条,且人工十查每一条都写了「已查,无问题」或「已修正(说明)」。
  **有未处理项就不交付。**

### 阶段五 · A/B 卷生成与等价性校验

**仅在 intake 第 9 项为「要 A/B 卷」时执行。**

- **输入**:通过质量门的 `题库.json` + `双向细目表.xlsx`。
- **动作**:
  1. **等价性五要素**(A 卷与 B 卷必须同时满足,缺一不算等价):

     | 要素 | 要求 | 怎么做到 |
     |---|---|---|
     | 同知识点 | 每个知识点的题数与占分百分比差 ≤ 2pp | 两卷共用同一张细目表,逐格对照 |
     | 同认知层次 | 每个层次的题数完全一致(或差 ≤ 1 题且占比差 ≤ 3pp) | 层次是格子的另一个维度,配题时锁定 |
     | 同难度 | 两卷全卷难度预估均值差 ≤ 0.03;单题难度差 ≤ 0.05 | 见「难度预估」公式,逐题算 |
     | 同分值 | 总分相同;每题分值序列可不同但**各题型分值合计相同** | 抄同一份配分方案 |
     | 不同题面 | 情境、数值、问法、选项内容都不同;**不是同一道题换选项顺序** | 见第 2 步 |

     > **明确禁止**:「同一套题,把选项顺序打乱当 B 卷」「把 A 卷题号重排当 B 卷」。
     > 这既不是等价性设计,也挡不住抄袭——学生只要看答案字母就知道对方卷子的对应题。
     > 选项乱序只能作为**额外的防抄袭措施**叠加在真正的 B 卷之上。

  2. **B 卷生成法(同格异构)**,对每个格子换轨:
     - **换情境**:A 卷「电梯加速上升」→ B 卷「汽车刹车」。
     - **换数值**:把 2kg/4N 换成 3kg/9N,并保证计算量相当(别一边心算一边要解方程)。
     - **换问法**:A 卷「求加速度」→ B 卷「求所受合力」。
     - **换可选性**:A 卷单选 → B 卷多选**不允许**(题型变了就不是同格);应保持题型不变。
     - **换干扰项但不换错误概念**:两卷同一题考的学生误区应来自同一组常见错误(如都考「把合力当某一个力」)。
  3. **选项乱序**(若教师要求):每道选择题独立打乱选项位置,用脚本或手工重排后**逐题核对答案字母同步更新**。
     答案位置分布 A/B/C/D 各占 25%±5%(沿用 `skills/ibook-skills/question-writing/SKILL.md` 的答案均衡要求),
     不得出现连续 3 题同字母、不得 A-B-A-B 循环。
  4. **等价性校验**(四步,全部留痕):
     - ① 两卷各跑一遍 `quiz_audit.py`,层次分布、题型分布、答案位置分布逐项对照,偏差超表即不合格。
     - ② 用同一张细目表逐格填两卷题号,输出 **A/B 对照表**(xlsx 工作表「AB卷对照」):
       行 = 知识点 × 层次,列 = `A卷题号 | A卷分值 | A卷难度 | B卷题号 | B卷分值 | B卷难度 | 难度差 | 合格?`。
     - ③ 全卷难度均值、各题型分值合计、题量逐项比对,写出差值。
     - ④ **人工逐题读一遍**:确认两卷没有「同一道题换皮」、没有「B 卷某题的答案能从 A 卷题干里读出来」。
  5. 生成防泄题提示:A/B 卷文件名与卷头**都要写清卷别**,交印时说明「两卷不得同场混用不同卷别」。
- **输出**:`试卷A.docx`、`试卷B.docx`、`参考答案A/B.docx`、`AB卷对照表.xlsx`、`等价性校验报告.md`。
- **退出条件**:等价性五要素逐项给出「实测差值」,全部在容差内;对照表无空格;人工逐题复核完成。

### 阶段六 · 参考答案与评分要点

- **输入**:`题库.json` 的 `answer` / `explanation` / `scoring_points`。
- **动作**:
  1. 客观题:给出答案字母/正误,附**解析**(为什么对、每个干扰项错在哪、考的是哪个知识点)。
  2. 主观题:按**得分点拆分**给评分要点,每个得分点标分值,分值合计必须等于该题满分;
     算例另附**典型错误与扣分口径**(如「只写公式不代入扣 3 分」)。
  3. 允许一题多解的题(计算、编程、证明),**每一类解法都要给一档评分口径**,不要让阅卷人自己判断。
  4. 留人工确认位:`【待教师确认:第 X 题第 (2) 问的给分口径是否按此执行】`。
  5. 本阶段只做**面向阅卷的评分要点**;完整的评分细则(rubric,含等级描述、阅卷培训口径、样卷标竿)
     交 `exam-pipeline` 做(见「交接协议」)。
- **输出**:`参考答案与评分要点.docx`。
- **退出条件**:评分要点每题分值合计 = 该题满分;每道主观题至少有 2 个可独立判分的得分点;人工确认位已写入。

### 阶段七 · 复习型题库与 FSRS 闪卡

**仅在 intake 第 10 项含「题库/练习/复习」或教师明确要求时执行。**

- **输入**:`题库.json`。
- **动作**:
  1. **先把题目转成「原子卡」**,不是把整道选择题抄成一张卡。转换规则:

     | 原题 | 拆成几张卡 | 卡正面 | 卡背面 |
     |---|---|---|---|
     | 一道考查 2 个知识点、含 3 个干扰项的选择题 | 1 + 干扰项数 | 「正常工作时,X 与 Y 的关系是?」 | 答案 + 一句话理由 |
     | 同上,另一个考点「为什么不是 Z」 | +1 | 「有人说 Z 也对,错在哪?」 | 该干扰项对应的**具体错误概念**及其纠正 |
     | 计算题 | 2 | ①「这类题的解题步骤是什么」②「本题关键代换是哪一步」 | 步骤 / 代换 |
     | 判断题 | 1 | 把判断句改成选择题式提问 | 判断 + 理由 |
     | 论述题 | 按小问数 | 每个小问一张 | 要点骨架(不是全文) |

     **遮挡原则**:一张卡只问一件事,正面不能出现答案线索,背面必须能在 20 秒内读完。
     判断题的卡正面**不要保留原句**(原句含答案),改成「X 与 Y 的关系是什么」。

  2. 卡片加入 FSRS,按 `skills/learning-education/study-skill/references/fsrs-spaced-repetition.md` 的协议执行。

     > ⚠️ **先做前置检查**:上游 `scripts/fsrs/` 里是 **Go 源码**(`go.mod` / `cmd/` / `internal/`),
     > 其 `.gitignore` 忽略了编译产物 `/fsrs`,**仓库并不附带可执行文件**。
     > 本机若未安装 Go 工具链,下面的命令会直接报 `No such file or directory`。

     ```bash
     # 前置检查:二进制在不在?没在就尝试构建
     FSRS_DIR="skills/learning-education/study-skill/scripts/fsrs"
     FSRS_BIN="$FSRS_DIR/fsrs"
     if [ ! -x "$FSRS_BIN" ]; then
       if command -v go >/dev/null 2>&1; then
         (cd "$FSRS_DIR" && go build -o fsrs ./cmd/...)   # 需 Go >= 1.22(见其 go.mod)
       else
         echo "未安装 Go 工具链,无法构建 FSRS 调度器 → 走下面的降级方案" >&2
       fi
     fi
     ```

     构建成功后按上游协议使用:

     ```bash
     FSRS_STORE=复习包/.fsrs/cards.json
     "$FSRS_BIN" add "kp-牛顿第二定律" "牛顿第二定律" 2      # <id> <主题> <初始难度 1-10>
     "$FSRS_BIN" schedule                                  # 查今天到期的卡
     "$FSRS_BIN" review "kp-牛顿第二定律" 3                 # 复习结果 1=忘了 2=难 3=记得 4=容易
     "$FSRS_BIN" status                                    # 全部卡片概览
     ```

     **降级方案(无 Go 时)**:不要假装命令能用。改为按 `fsrs-spaced-repetition.md` 的
     D/S/R 三值与 1–4 评分口径,**用表格手工排程**——在 `复习包/闪卡排程表.xlsx` 中为每张卡
     记录 `首次学习日 / 当前间隔 / 难度 / 上次评分 / 下次复习日`,并按「评分 1→次日、2→2 天、
     3→按当前间隔×2、4→按当前间隔×2.5」推进。同时在 `闪卡导入说明.md` 里注明
     「本包按 FSRS 口径手工排程,如需自动调度请安装 Go 后构建上游二进制」。
     这条降级路径必须写进交付说明,**不得让教师以为拿到了自动化排程**。

     无论走哪条路:初始难度直接取该题 `est_difficulty` 的映射(`est_difficulty ≤0.5 → 8`、
     `0.5–0.7 → 5`、`>0.7 → 3`),别把所有卡都设成同一个值——FSRS 靠它算首次间隔。
     每次复习呈现**最多 3 条**,单次不超过 5 分钟(沿用 study-skill 的混合复习模型)。

  3. 卡片 JSON 与题库 JSON 用 `card_id` 关联,便于「某道题答错 → 找到对应卡片 → 加强复习」。
- **输出**:`复习包/题库.json`(卡字段:`card_id / kp / front / back / difficulty / source_qid`)、
  `复习包/.fsrs/cards.json`、`闪卡导入说明.md`(怎么用 FSRS 命令、怎么在考前一天集中复习)。
- **退出条件**:每张卡正面不泄露答案;卡数与知识点覆盖对得上;且 `fsrs status` 能列出全部卡片**(走降级方案时为:`复习包/闪卡排程表.xlsx` 覆盖全部卡片,且交付说明已注明「手工排程」)**。

### 阶段八 · 交付(office-layer 唯一通道)

- **输入**:阶段三~七的全部产物。
- **动作**:

  ```bash
  PY="skills/office-layer/.venv/bin/python"

  # 试卷(Markdown 草稿 → docx;卷头用 Markdown 表格写「题号/一/二/三/总分」得分栏)
  $PY skills/office-layer/scripts/docx_kit.py md \
      --in 试卷A.md --out 试卷A.docx \
      --title "【待补:学校名】20XX—20XX学年第一学期《【待补:课程名】》期末考试试卷(A卷)"
  $PY skills/office-layer/scripts/docx_kit.py inspect --in 试卷A.docx

  # 参考答案与评分要点
  $PY skills/office-layer/scripts/docx_kit.py md --in 参考答案A.md --out 参考答案与评分要点A.docx

  # 需要页眉页脚 / 密封线说明 / 人工确认位的《命题说明与审核单》走 spec
  $PY skills/office-layer/scripts/docx_kit.py spec --spec 命题说明.json --out 命题说明与审核单.docx

  # 双向细目表 / 覆盖矩阵 / 难度预估 / 答案位置校验 / AB卷对照(多工作表 + 原生图表)
  $PY skills/office-layer/scripts/xlsx_kit.py build --spec 细目表.json --out 双向细目表.xlsx
  $PY skills/office-layer/scripts/xlsx_kit.py inspect --in 双向细目表.xlsx
  ```

  细目表 spec 结构(`xlsx_kit.py build` 支持 `sheets[].{name,header,rows,freeze,widths,chart}`):

  ```json
  {"sheets": [
    {"name": "双向细目表",
     "header": ["知识点","重要度","题型","认知层次","题号","题数","分值","占分比","难度预估"],
     "rows": [["牛顿第二定律","A","计算","应用","Q12",1,12,"12%",0.60]],
     "freeze": true},
    {"name": "知识点覆盖矩阵",
     "header": ["知识点","重要度","识记","理解","应用","分析","合计题数","合计分值"],
     "rows": [["牛顿第二定律","A",0,1,2,0,3,19]]},
    {"name": "难度预估",
     "header": ["题号","题型","预计难度 P","满分","预计平均得分"],
     "rows": [["Q12","计算",0.60,12,7.2]],
     "chart": {"type": "bar", "title": "各题预计难度", "value_col": 3, "height": 9, "width": 18}},
    {"name": "答案位置校验",
     "header": ["选项位置","题数","占比","合格线(25%±5%)"],
     "rows": [["A",6,"24%","合格"]]}]}
  ```

  1. **写完必须 `inspect` 读回**:确认段落数、表格数、图表数、字数符合预期,别交一个空壳 docx。
  2. 卷面检查(打印预览视角):题号连续无跳号;得分栏与题号对应;跨页处不把一道题劈两半;
     主观题留够作答空间(简答 ≥6 行、论述/案例 ≥10 行或注明「另附答题纸」)。
  3. 交付说明里写清:本次用了哪些默认值、哪些字段是 `【待补:…】`、**「本文件为出题初稿,全部题目须经教师逐题审核后方可进考场」**。
- **输出**:见「产出物」一节的文件清单 + `交付说明.md`。
- **退出条件**:每个 docx/xlsx 都 `inspect` 通过;三种占位(`【待补:…】`、`【待教师确认:…】`、`【待补:依据出处】`)在交付说明里被列出。

### 阶段九 · 交接给 exam-pipeline

- **输入**:阶段八的全部交付文件。
- **动作**:按「与 exam-pipeline 的交接协议」一节打包,写到同一个交接目录,并把字段清单核对一遍。
- **输出**:`handoff/` 目录(含 `manifest.json`)。
- **退出条件**:`manifest.json` 里每个文件路径都存在且非空;`questions` 数组条数 = 细目表题数;
  下游需要的字段没有空值(除显式标注 `【待补】` 的)。

## 题型设计参考(八种题型)

每种题型给出 **适用场景 / 命题要点 / 好题标准 / 常见命题缺陷**。出题时按细目表的格子查这一节。

### 1. 单项选择题

- **适用场景**:覆盖面最广的客观题。识记、理解、应用三个层次都能用;一次考一个明确结论。适合题量大、要覆盖多考点的正式考试。
- **命题要点**:
  - 题干是一个**完整的问题或未完成的陈述**,不写「下列说法正确的是」这种无指向的开头(除非考概念辨析,且选项是互斥表述)。
  - 一题只考**一个**知识点、**一个**结论。要考两个考点就出两题。
  - 选项 4 个(不得 3 个凑数、不得 5 个以上混排),长度基本相当,语法与题干衔接一致。
  - 正确项**位置随机**,全卷 A/B/C/D 各约 25%。
  - 每个干扰项对应一条可写出来的学生常见错误。
- **好题标准**:
  - [ ] 读完题干就知道要回答什么,不用猜出题人意图
  - [ ] 正确项是唯一可辩护的答案(另有人能"说得通"就是废题)
  - [ ] 三个干扰项各自对应不同类的错误概念,删掉任一都会让题目变简单
  - [ ] 不会做的学生靠常识/排除法也蒙不出来,但学懂了的学生一定选得对
  - [ ] 选项无「以上都对/都不对」,无绝对化词(一定/绝不/完全)
- **常见命题缺陷**:
  - ❌ 「以上都不对」凑第四个选项 → 题目退化成三选一,且掩盖干扰项设计失败
  - ❌ 正确项明显最长/最详细/唯一带修饰语 → 答案被长度泄露
  - ❌ 选项互相包含(「A 与 B」「A 或 B」)→ 逻辑上多解
  - ❌ 题干本身已含答案线索(「在牛顿**第二**定律 F=ma 中,加速度与合力的关系是…」)
  - ❌ 靠刁钻细节或单位符号区分(考的是记忆而非理解)
  - ❌ 否定式题干「下列哪项**不属于**」→ 见「命题质量原则 §2」

### 2. 多项选择题

- **适用场景**:辨析"几个说法各自对错"的场合;理解与分析层次;考查概念的边界(哪些属于、哪些不属于、哪些条件必须满足)。
- **命题要点**:
  - 正确项数量**事先规定**(常见 2 项或 2–3 项),并在卷头**写明评分规则**(全对得满分 / 漏选得部分分 / 多选不得分)。
  - 每个选项都应当**独立可判**(对就是对、错就是错),不得靠"程度"或"见仁见智"定对错。
  - 干扰项与正确项必须同质同层:要么都是条件、要么都是例子、要么都是定义要素,不许混。
  - 题量不宜多(一份期末卷 2–4 题),分值不超过总分 20%。
- **好题标准**:
  - [ ] 评分规则印在卷头,学生知道怎么得分
  - [ ] 每个选项都能独立判真假,不需要考虑其他选项
  - [ ] 正确答案数符合预设(如 2 项),不是"恰好一个选项全对"的单选题伪装
  - [ ] 漏选一个正确项、多选一个错误项,都能反映不同理解缺陷
- **常见命题缺陷**:
  - ❌ 正确项数是 1 → 与单选题重复,白白增加阅卷成本
  - ❌ 选项之间互为条件("若 A 对则 B 对")→ 组合起来无唯一答案
  - ❌ 部分选项边界模糊("通常""有时"),学生无法判断
  - ❌ 不写评分规则 → 全对/漏选/多选三种情况教师自己都要现场想
  - ❌ 题干用「以下哪些是…」却只有一个是教材原文表述,其余是同义改写 → 考的是措辞不是知识

### 3. 填空题

- **适用场景**:术语、公式、关键数值、步骤名的精确记忆(识记层);覆盖密度高、阅卷快。
- **命题要点**:
  - 一空只填**一个**确定答案,答案是**唯一且无歧义**的(同义表述要预先列出可接受写法)。
  - 空格处挖的是**术语/结论/公式的关键部分**,不要挖连接词、虚词、标点。
  - 空格数量与分值匹配(通常每空 1–2 分),一题不要超过 5 空。
  - 需要单位、正负号、有效数字的,题干里明确要求("结果保留两位有效数字并注明单位")。
- **好题标准**:
  - [ ] 空格的答案唯一;若有多种正确写法,参考答案里列全
  - [ ] 不挖掉答案就会让题目变成照抄教材原句(**不得直接照搬教材原题/原句**)
  - [ ] 上下文足够推断出该填什么类型的答案(术语?数值?公式?)
  - [ ] 空格位置不影响句子的语法可读性
- **常见命题缺陷**:
  - ❌ 一空多解或答案可推断出多个合理值 → 阅卷无法统一口径
  - ❌ 挖掉的字数暗示答案长度(短线长短不一)
  - ❌ 直接抄教材原句挖空 → 违反红线(见「红线」第 1 条)
  - ❌ 前后两句互相给出答案(前面填了 X,后面那空就是 X 的同义)
  - ❌ 数值题不要求单位/精度,学生答案五花八门

### 4. 判断题

- **适用场景**:快速检验概念边界与常见误解(理解层),适合随堂小测与形成性检查。
- **命题要点**:
  - 陈述句必须**非真即假、可证伪**,不许出现"基本正确""大体上成立"这种中间态。
  - **真、假两类的数量大致均衡**(约各半),且真假在卷面上无规律排列。
  - 错误陈述要**错在关键概念上**(正是学生容易搞混的那一点),不要错在无关紧要的修饰词上。
  - 要求写理由时,分值要拆开(判断 1 分 + 理由 2 分),并在卷头写明。
- **好题标准**:
  - [ ] 判定为假时,能一句话说清错在哪个概念(这句就是解析)
  - [ ] 真假分布均衡,看不出规律
  - [ ] 陈述不使用"总是""绝不""一切"这类词来制造错误(那是送分)
  - [ ] 加"说明理由"时,理由的判分口径可操作
- **常见命题缺陷**:
  - ❌ 用绝对化词造错("所有物体都…")→ 学生一看就选错,零区分度
  - ❌ 全部为真(或全部为假)→ 学生全打勾就得满分
  - ❌ 陈述含歧义表述 → 硬判"对"或"错"都站不住
  - ❌ 把两个独立命题用"并且"拼起来,一半对一半错 → 判分无意义
  - ❌ 只判不说明理由,考不出理解深度

### 5. 简答题

- **适用场景**:理解与分析层;要求用自己的话说明概念、关系、原因、区别;比填空题更能看出学生是否真懂。
- **命题要点**:
  - 一问一答,**题面指明要答几点**("从三个方面说明…""写出两条区别"),避免学生漫天写。
  - 标准答案给**要点清单**,每个要点独立给分,不要求文字与教材一致。
  - 限定作答篇幅("不超过 200 字"),防止写满页碰分。
  - 分值 4–8 分为宜;超过 10 分应拆成多个小问。
- **好题标准**:
  - [ ] 答案要点能列成 3–5 条,条条可独立判分
  - [ ] 题面限定了答题方向与数量,学生知道答到什么程度
  - [ ] 不需要长篇论述就能答全(长篇论述是论述题的事)
  - [ ] 得分点与分值一一对应,无"酌情给分"这类模糊空间
- **常见命题缺陷**:
  - ❌ 「谈谈你对 X 的理解」→ 没有边界,无法统一评分
  - ❌ 答案要点几十条,阅卷时只能"看着给" → 违反 `exam-pipeline` 的可操作评分口径
  - ❌ 题目本身就能从题干推出答案(自问自答式题干)
  - ❌ 简答题里塞了需要计算或设计的内容 → 题型错配
  - ❌ 只给"参考答案"不给得分点拆分 → 阅卷人各自为政

### 6. 计算题

- **适用场景**:应用与分析层;理工、经管、统计类课程的核心题型。
- **命题要点**:
  - 数据要**算得完**:按 intake 第 11 项时长,中等水平学生 3–5 分钟一题;三步以上的代入要给中间数。
  - 必须规定精度与单位(有效数字、单位、方向),并在参考答中给出**扣分口径**。
  - 题干给出**必要的已知条件**,且条件不多不少(多给条件会误导,少给条件做不出)。
  - **分层设问**:(1) 列式/建模(2) 求解(3) 讨论结果合理性,让部分会做的学生也能拿分。
  - 数值要合理:别出现加速度 10⁹ m/s² 这种脱离物理常识的结果;除不尽时预设"保留两位小数"。
- **好题标准**:
  - [ ] 正确答案可复算(教师自己按参考答案算一遍结果一致)
  - [ ] 每一步都有独立得分点,写对过程但不写答案能得部分分
  - [ ] 允许一题多解时,每种解法都有对应评分口径
  - [ ] 不需要计算器也能完成(若闭卷且不允许计算器)
  - [ ] 结果有物理/经济意义(不是纯数字游戏)
- **常见命题缺陷**:
  - ❌ 数据除不尽又没规定精度 → 学生答案千奇百怪,阅卷无法统一
  - ❌ 漏给单位或坐标系约定 → 符号正负无法判定
  - ❌ 只给最终答案分,不看过程 → 鼓励背答案
  - ❌ 计算量过大(纯算术苦工),把懂物理的学生挡在时间之外
  - ❌ 数据凑得太巧妙(答案正好是整数)→ 学生反推出题人的数字游戏,实际没懂
  - ❌ 题干条件与问题不匹配(给了用不上的条件,或有条件没说)

### 7. 论述题

- **适用场景**:分析、评价、创造层;考查论证能力、多角度思考、学科语言表达。适合人文社科、教育学、管理学等课程的高分值题。
- **命题要点**:
  - 题面要给出**作答角度或要求**("结合 X 理论,从 A、B 两个层面分析…"),并说明能否结合课程外材料。
  - 用**小问链**降低评分难度:3 个递进小问(是什么 → 为什么 / 怎么分析 → 你怎么评价),
    小问按苏格拉底式追问设计——后一问必须用到前一问的结论,且能区分事实/解释/价值判断。
  - 评分按**能力维度分档**(如"论证结构 10 分 / 理论运用 8 分 / 语言规范 2 分"),每档写出等级描述。
  - 分值 ≥15 分,且**必须留足作答空间**或注明用答题纸。
- **好题标准**:
  - [ ] 题面限定了论述范围与角度,但**不预设结论**(不许"论述 X 的先进性"这种诱导式提问)
  - [ ] 小问层层递进,前一问是后一问的前提
  - [ ] 分档评分标准(优秀/良好/合格/不合格)四档描述可操作,两位教师评同一份卷能得相近分数
  - [ ] 不查资料(闭卷)也能完整作答,不需要记忆冷僻文献
  - [ ] 不要求引用具体文献(教师没给的都不许学生"必须引用",也不许 AI 替题面编文献)
- **常见命题缺陷**:
  - ❌ 「谈谈你的看法」→ 无评分锚点
  - ❌ 题面已经暗示立场("为什么说 X 是正确的")→ 封闭式假论述
  - ❌ 一道 20 分大题不给任何结构提示 → 区分的是写作速度而非理解
  - ❌ 小问之间互不相干((1) 定义 (2) 举例 (3) 你的感想)→ 不是论证链,是三道小题拼盘
  - ❌ 要求"结合课程文献"但教师从未提供文献清单 → 学生无从下手
  - ❌ 只写"言之成理即可" → 与 `exam-pipeline` 的评分细则无法对接

### 8. 案例分析题

- **适用场景**:应用、分析、评价层;把真实/拟真情境交给学生诊断与决策。适合医学、法学、教育学、管理学、社会工作、工程故障诊断等。
- **命题要点**:
  - 案例要有**完整情境**:背景、已有信息、约束条件、待决问题;必要数据以表格/图表给出(非连续文本题式)。
  - 案例**可以是真实改编,但必须脱敏**:不得含真实姓名、单位、病历号、案件号;改编处不虚构具体数据与结论。
  - 设问按**临床/实务决策链**递进:识别问题 → 分析成因 → 提出方案 → 论证方案与风险。
  - 标注案例来源:`【案例来源:教师提供 / 公开报道改编(写明来源)/ 为教学目的拟制】`。
    **不得虚构来源**、不得编造真实机构与真实数据。
  - 分值 15–25 分;评分按"问题识别 / 理论运用 / 方案可行性 / 风险与伦理"分维度给分。
- **好题标准**:
  - [ ] 案例本身信息充足,学生不需要额外查资料就能作答
  - [ ] 案例不含真实可识别身份信息
  - [ ] 多个设问共享同一案例,形成完整决策链
  - [ ] 允许存在多个合理方案,评分口径写"论证质量"而非"标准答案"
  - [ ] 案例来源如实标注,拟制案例也明确写"为教学目的拟制"
- **常见命题缺陷**:
  - ❌ 案例是"套了外衣的简答题"(换个人名问同一个定义)
  - ❌ 案例信息不足,学生只能凭常识猜 → 考不出课程内容
  - ❌ 案例来源不明或编造来源 → 违反「不虚构引用来源」红线
  - ❌ 只给一个设问「请分析该案例」→ 无作答结构
  - ❌ 案例涉及真实机构/个人的负面评价 → 教学伦理问题

### 按用途默认配比(intake 第 5 项缺省时用)

| 用途 | 题量 | 题型配比建议 | 层次配比 |
|---|---|---|---|
| 随堂小测 / 课前测 | 3–5 题 | 单选 3 + 判断 1 + 简答 1 | 识记 30 / 理解 50 / 应用 20(覆盖当前一次课的知识点,**不追求全课覆盖**) |
| 单元测 | 15–20 题 | 单选 40% + 多选 10% + 填空 15% + 判断 10% + 简答 15% + 计算/案例 10% | 识记 25 / 理解 30 / 应用 30 / 分析 15 |
| 期中 | 20–25 题 | 单选 30% + 多选 10% + 填空 15% + 简答 20% + 计算/案例 25% | 识记 20 / 理解 30 / 应用 30 / 分析 20 |
| 期末 | 25–35 题 | 单选 25% + 多选 10% + 填空 10% + 判断 5% + 简答 20% + 计算/案例/论述 30% | 识记 20 / 理解 25 / 应用 30 / 分析 20 / 评价 5 |
| 补考 | 与正考同 | 同正考题型配比,**同知识点同层次**,全部换题面 | 与正考同分布 |
| 练习题库 | 不限 | 以单选+填空为主,便于自测 | 可放宽,练习卷不必严格配比 |

## 命题质量原则

### 1. 干扰项设计

直接按 `skills/ibook-skills/question-writing/references/distractor-writing-guide.md` 执行,落到本技能的纪律:

**干扰项必须有来源。** 每写一个干扰项,回答一句「它对应哪条学生常见错误」。
来源优先级(沿用 `k12-check-for-understanding` 对"有据可查的常见错误"的要求):

1. 教师提供的**往年错题记录 / 作业错例 / 课堂提问中的典型错答**(最强证据,优先用)
2. 教师提供的**教学经验说明**("学生总把 X 和 Y 搞混")
3. 学科内**公认的典型误解**(如物理的"力是维持运动的原因"、统计的"p 值等于原假设为真的概率"、编程的"值传递与引用传递混淆")
4. 由**知识点的邻近概念**构造(把相邻概念的属性安到本概念上)

四条都拿不到时,**留空并标注** `【待教师补充:本知识点学生的典型错误】`,不要凑选项。

**四类构造法**(来自指南,直接用):

| 构造法 | 说明 | 例(滑轮/受力) |
|---|---|---|
| 部分真理 | 换个语境就成立,但不回答本题 | 「合力为零则加速度为零」(对,但答非所问) |
| 反向 | 把关系方向颠倒 | 「绳子张力等于物重」↔「物重等于张力」(在加速系统里错) |
| 近似术语 | 用相邻概念的名词 | 「动量」↔「动能」、「相关」↔「因果」 |
| 典型错误 | 学生算错的中间结果 | 忘记方向正负号得出的负值 |

**禁用项**(红线级):

- ❌ 「以上都对 / 以上都不对」(除非是全卷唯一一题且明确要考"全称判断",一般不批)
- ❌ 玩笑项、无意义项、明显不可能项("紫色的大象")
- ❌ 与正确项**同义**的干扰项(会造成两个正确项)
- ❌ 语法与题干不衔接、长度明显偏离
- ❌ 用绝对化词(一定/绝不/完全)来制造的"送分型错误项"

**干扰项质量分**(0–1,沿用指南口径):可信 0.8+、有教学价值、公平。
每题三个干扰项取平均,**全卷平均 ≥0.80**;低于 0.6 的干扰项必须重写,并在自检报告里列出改写前后对照。

### 2. 题面与选项的"泄露"防治(人工十查)

| # | 查什么 | 不合格的样子 | 怎么改 |
|---|---|---|---|
| 1 | 否定式题干 | 「下列**不属于**…」「以下**错误**的是」 | 改成正面提问,或把否定词加粗并在卷头提示 |
| 2 | 题干暗示 | 题干里出现正确项的关键词;长篇铺垫最后才问 | 把铺垫压到最短,把关键词从中性化 |
| 3 | 答案长度泄露 | 正确项最长/最详细/唯一带从句 | 四项长度差控制在 ±20% 内(脚本会报 >1.4 倍) |
| 4 | 语法不平行 | 选项 A 是名词短语、B 是完整句 | 统一句式(都以"的…"或都从动词起) |
| 5 | 选项互相包含 | 「A」「A 与 B」并列 | 让选项互斥;要考组合就改成多选 |
| 6 | 跨题泄露 | 第 3 题题干里有第 7 题的答案 | 全卷串读一遍,按考点扫描重复表述 |
| 7 | 卷内自答 | 题干里的数据直接给出答案 | 重新设计数据或增加一步推理 |
| 8 | 主观题分值与小问数不匹配 | 20 分只问一句 | 拆小问,或将分值降到与学生工作量相称 |
| 9 | 全卷无压轴 / 全卷无易题 | 全是中等题 → 区分度集中在同一水平段 | 回阶段二重排难度 |
| 10 | 与教材原题雷同 | 题干、数据、选项与教材例题逐一对应 | 换情境/换数值/换问法;**禁止照搬(红线)** |

> 第 1、3、6 条是高校考试最常被督导挑出来的问题,务必逐条留痕。

### 3. 认知层次分布(布鲁姆)

**默认目标比例**(intake 第 7 项):

| 层次 | 目标占比 | 典型指令动词 | 适配题型 |
|---|---|---|---|
| 识记 | **20%** | 写出、列举、识别、命名、陈述 | 单选、填空、判断 |
| 理解 | **30%** | 解释、说明、比较、区分、举例 | 单选、多选、填空、简答、判断 |
| 应用 | **30%** | 计算、求解、运用…解决、实施 | 计算、单选、案例分析、多选 |
| 分析 | **20%** | 分析、诊断、找出原因、辨别关系 | 案例分析、简答、论述、单选 |
| (评价 / 创造) | 0%(需要时从分析里让出,总计 ≤10%) | 评价、判断、设计、提出方案 | 论述、案例分析、设计题 |

容差 **±5 个百分点**;单份试卷的层次占比需与 intake 第 7 项一致,改比例必须回改细目表。

**按学生层次调整**:

| 学生层次 | 建议比例(识记/理解/应用/分析以上) |
|---|---|
| 本科低年级 / 高职 | 30 / 35 / 25 / 10 |
| 本科高年级 | 20 / 30 / 30 / 20 |
| 研究生 | 10 / 20 / 30 / 40(含评价与创造) |
| 专升本 / 补修 | 35 / 35 / 20 / 10 |
| 留学生(中文授课) | 30 / 35 / 25 / 10(并降低题干语言复杂度,专业术语保留中文+附原文) |

**判断陷阱**:一个题目的层次由**学生要做的思维动作**决定,不由知识点难度决定。
"写出牛顿第二定律的表达式"再难也是识记;"判断这三个情境中哪个满足第二定律的适用条件"是理解或应用。
出完题后回头自检一句:「这道题允许学生靠背诵作答吗?」能背就说明层次标高了。

### 4. 难度预估与分值匹配

**难度预估公式**(P = 预计得分率,越大越容易;与 `office-layer/scripts/xlsx_kit.py analyze` 的实测口径一致,便于考后对比):

```
P_预估 = 基础难度系数(按层次) − 结构惩罚项
  识记 0.90   理解 0.78   应用 0.65   分析 0.50   评价/创造 0.40
  结构惩罚(可累加,每项 0.05,最多 0.20):
    · 需要两步以上推理
    · 情境陌生、需要自己建模
    · 数值需要取整/开方
    · 题干较长(>120 字)
    · 需要跨知识点综合
```

各题**预计平均得分 = P_预估 × 该题满分**;全卷预计平均分应落在 intake 第 6 项的目标分 ±5 分内。
不落在区间内就调题:把最难题移到下个层次 / 减一个情境 / 增加已知条件。

**目标分的卷型口径(先定口径,再校验)**:上面公式的层次系数对应的是**得分率**,
不是难度等级。按层次目标配比(识记 20/理解 30/应用 30/分析 20)直算,客观题为主
的卷型(客观题分值占比 ≥60%)全卷预估均值约 75,对应默认目标 **75±5**;
**主观题占比高的卷型(简答/计算/案例/论述合计 >40%)全卷预估均值天然落在 60–70**,
此时应把目标分改为 **65±5**(intake 第 6 项由教师确认),不要为了让预估「达标」
而虚报 P 值或砍高阶题——高阶题少、预估均值低,是卷型特征,不是命题失误。
预估与目标不一致时的处理顺序:①确认卷型口径是否选对 → ②真偏高就调题 →
③真偏低就向教师说明并改目标分,留 `【待教师确认:目标分口径】`。

**易中难比例**:`P ≥ 0.75 为易`、`0.50 ≤ P < 0.75 为中`、`P < 0.50 为难`;
默认 **易:中:难 = 3:5:2**(按题数占比,不是分值占比)。

**分值匹配原则**:

1. **分值 = 作答时长配额 × 单位分**。以 100 分为例:

   | 题型 | 每题基准分 | 说明 |
   |---|---|---|
   | 单选 | 2–3 分 | 1–1.5 分钟/题 |
   | 多选 | 4–5 分 | 2–2.5 分钟/题 |
   | 填空 | 每空 1–2 分 | 0.5–1 分钟/空 |
   | 判断 | 1–2 分(要理由则 3–4 分) | 0.5–1 分钟/题 |
   | 简答 | 4–8 分 | 4–6 分钟/题 |
   | 计算 | 8–15 分 | 6–12 分钟/题 |
   | 案例分析 | 15–25 分 | 15–25 分钟/题 |
   | 论述 | 15–25 分 | 20–30 分钟/题 |

2. 全卷**作答时间合计 ≤ 考试时长的 85%**,留出检查时间。超了就减题量,不要压缩分值(压分值会让阅卷口径变形)。
3. 层次分值与分值配额**分开看**:高分值题不等于高难度题;一道 20 分的案例分析可以只到"分析"层。
4. 分值分配表要与细目表**双向对齐**:细目表各格分值之和 = 卷面总分 = 各题型分值之和。
5. 考后把实测 P(`xlsx_kit.py analyze` 给出)与预估 P 对比,写入《预估偏差说明》回填题库,
   下一轮出题直接用历史实测值校准——这是本技能越用越准的关键。

### 5. 卷内一致性

- 同一份卷子里,**不同题目之间不得互相提示答案**(查第 6 条)。
- 同一知识点的多道题,层次要有梯度(识记 → 应用),不要三道都是识记。
- 全卷题干语言风格统一(都用"求…"或都用"请说明…"),不要前松后紧。
- 术语与符号全卷统一(前面用 F 后面不能变成 f;前面用"加速度"后面不能变成"加速率")。
- 卷头必须写明:考试时长、总分、闭卷/开卷、可否用计算器、多项选择题的评分规则。

## 按知识点覆盖出题(题量规划方法)

### 1. 知识点从哪里来(优先级降级链)

```
① 教师给的知识点清单 / 考纲(最优先,直接用)
② 教学大纲的章节条目 + 学习成果(抽成知识点,回读确认)
③ 教材目录 + 每节的小标题(抽成知识点,回读确认)
④ 教师给的讲义/材料正文 → 按小节抽知识点(抽完必须回读确认,且标注"由材料自动抽取")
```

③④ 两种情况下,用 `skills/ibook-skills/learning-graph-generator/` 的思路建知识点依赖,
并用 `skills/ibook-skills/course-description-analyzer/` 抽取布鲁姆层次的学习成果;
若教师只给一章,不必生成全图。

### 2. 从知识点清单到题量的算法

```
步骤 1  给每个知识点定级(A 核心 / B 支撑 / C 了解),权重 A=3 B=2 C=1
步骤 2  算总权重 W = Σ权重
步骤 3  该知识点题数 n_i = round(总题量 × 权重_i / W)
步骤 4  整数化修正:
          A 级 n_i < 1 → 提到 1(核心考点不许 0 题)
          C 级 n_i ≤ 0.4 → 归 0(了解性内容不必占分)
          修正后的合计与总题量的差,用"优先级顺序"补/减:
            补:先给 A 级中权重最高且题数最少的;减:先减 C 级
步骤 5  每个知识点的 n_i 题再分到布鲁姆层次,命中全局层次比例
步骤 6  每格选一个题型(按「题型设计参考」的适配表)
步骤 7  配分(按「命题质量原则 §4」的基准分)
```

**题量参考线**(不是硬性规定,看 intake 第 4 项):

| 场合 | 题量 | 单个知识点平均题数 |
|---|---|---|
| 随堂小测 | 3–5 | 1(只覆盖本次课 2–3 个知识点) |
| 单元测 | 15–20 | 1.5–2 |
| 期中/期末 | 25–35 | 2–4(A 级知识点 3–4 题,C 级 0–1 题) |
| 题库/练习 | 不限 | 每知识点 3–5(含变式) |

### 3. 覆盖矩阵(知识点 × 题型 × 认知层次)

**这就是阶段二的产出核心**。表格形式(xlsx 工作表「知识点覆盖矩阵」),每格填**题数**(括号里填题号):

| 知识点 | 重要度 | 单选·识记 | 单选·理解 | 多选·应用 | 填空·识记 | 简答·分析 | 计算·应用 | 案例·分析 | 合计题数 | 合计分值 | 占分比 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 牛顿第一定律 | A | 1(Q1) | 1(Q5) | | 1(Q9) | | | | 3 | 8 | 8% |
| 牛顿第二定律 | A | | 1(Q2) | 1(Q8) | | | 1(Q12) | | 3 | 19 | 19% |
| 牛顿第三定律 | A | | 1(Q3) | | | 1(Q16) | | | 2 | 8 | 8% |
| 动量守恒 | A | | | | | | 1(Q13) | 1(Q18) | 2 | 22 | 22% |
| 角动量守恒 | C | | 1(Q4) | | | | | | 1 | 3 | 3% |
| **合计** | | **1** | **4** | **1** | **1** | **2** | **2** | **1** | **12** | **60** | **100%** |

**覆盖率怎么报**(写进自检报告):

```
知识点覆盖率 = 已出题的知识点数 / 知识点清单总数
  A 级知识点覆盖率必须 = 100%(核心考点一题不落)
  全卷覆盖率:随堂小测按"本次课知识点"算(要求 100%)
             期中期末按整门课清单算(要求 ≥70%,且未覆盖的必须是 C 级)
```

未覆盖的知识点**必须逐条列出并说明为什么不考**(如"本章不纳入期末范围""仅作阅读材料"),
不许静默省略——教师看到"没覆盖"才知道是设计选择还是遗漏。

### 4. 细目表 xlsx 的工作表结构

| 工作表 | 内容 |
|---|---|
| 双向细目表 | 行=题号,列=知识点/重要度/题型/认知层次/难度预估/分值/占分比/预计平均得分 |
| 知识点覆盖矩阵 | 上面那张交叉表(知识点 × 题型·层次) |
| 题型分布 | 各题型的题数、分值、占分比、建议区间、是否合格 |
| 层次分布 | 各认知层次的题数、分值、实际占比、目标占比、偏差(pp)、是否在 ±5pp 内 |
| 难度预估 | 逐题 P 值与预计平均得分 + 全卷预计平均分 + 易中难比例 + 原生柱状图 |
| 答案位置校验 | A/B/C/D 各位置题数、占比、是否在 25%±5%(多选与主观题不计入) |

## A/B 卷生成

### 1. 等价性要求(五要素,逐项必须可测量)

| 要素 | 量化容差 | 校验方式 |
|---|---|---|
| 同知识点 | 各知识点题数一致;占分比差 ≤ 2pp | 细目表逐格对照(AB卷对照表) |
| 同认知层次 | 各层次题数一致或差 ≤1 题,占比差 ≤ 3pp | `quiz_audit.py` 两卷输出对照 |
| 同难度 | 全卷预估 P 均值差 ≤ 0.03;单题差 ≤ 0.05 | 逐题 P 值求差 |
| 同分值 | 总分相同;各题型合计分值相同 | 题型分布表对照 |
| 不同题面 | 题干相似度低(前 12 字不得雷同);数据、情境、问法都不同 | 脚本雷同检测 + 人工逐题读 |

### 2. 生成流程

```
1. 复制细目表 → 作为两卷共用模板(这是保证等价的前提,不要各写一张)
2. 对每一格:先出 A 卷题,再按"同格异构"四换法(换情境/换数值/换问法/换干扰项)
   出 B 卷题,并把两题的 kp / bloom / score / est_difficulty 保持同值
3. 若要求选项乱序:每卷独立乱序,逐题同步更新答案字母
4. 两卷各跑 quiz_audit.py + 生成 AB卷对照表
5. 人工逐题复核(这一步不能省,脚本查不出"换皮题")
6. 卷头分别标注"(A 卷)""(B 卷)",并注明"两卷等值,不得同场混用不同卷别"
```

### 3. 等价性校验报告要写什么

- 五要素逐项的**实测差值**(不是"应该差不多",要有数字)
- `AB卷对照表` 的行数与细目表格数一致(无空格)
- 两卷的题型分布、层次分布、答案位置分布并排对照表
- 脚本雷同检测结果(0 条为合格)
- 人工复核结论:逐题说明「B 卷该题与 A 卷的差异点在哪」(每个格子一句)
- 未达标项与处理动作(重出题 / 调整难度 / 换情境),以及处理后重跑的差值

### 4. 常见不合格情形

- ❌ 只是把 A 卷题号重排 → 不是 B 卷
- ❌ A/B 卷难度均值差了 0.1 以上(一门课平均分能差 8 分)
- ❌ B 卷某个知识点的题数比 A 卷少 1 题(考点覆盖不对等,学生申诉的常见由头)
- ❌ B 卷某题情境与 A 卷几乎一致,只改了数字 → 学生互相一看就穿
- ❌ 两卷多选评分规则写得不一样 → 即使题目等值,得分不具可比性

## 复习型题库与闪卡(引用 FSRS)

沿用 `skills/learning-education/study-skill/` 的 FSRS 间隔重复体系,把题目变成可长期复习的卡片。

### 1. 为什么不是"把题目存成题库"就够了

题目是**测评工具**(一次性、要计分),闪卡是**记忆工具**(重复出现、不计分)。
直接把选择题塞进复习只会让学生记住选项位置。所以要**拆卡**:

| 原则 | 做法 |
|---|---|
| 一卡一事 | 一道考两个考点的题拆成两张卡 |
| 正面不泄露 | 判断题的卡正面去掉原判断句,改成提问式 |
| 背面 20 秒可读完 | 只放答案 + 一句话理由,不放整段解析 |
| 干扰项变独立卡 | 每个干扰项对应一条常见错误,单独成卡:「有人说 X,错在哪?」 |
| 关联回原题 | 每张卡记 `source_qid`,学生答错原题时能定位到卡 |

### 2. 卡片字段与题库的关联

```json
{
  "card_id": "kp-牛顿第二定律-c2",
  "kp": "牛顿第二定律",
  "front": "处于加速上升的电梯中,人对地板的压力与自身重力相比如何?",
  "back": "更大。因为加速度向上,合力向上,地板支持力 N = m(g+a) > mg。",
  "difficulty": 5,
  "source_qid": "Q07",
  "misconception": "认为压力始终等于重力"
}
```

`difficulty` 初值由原题的 `est_difficulty` 映射:`≤0.5 → 8`、`0.5–0.7 → 5`、`>0.7 → 3`(1–10 分制)。

### 3. FSRS 操作(照 `references/fsrs-spaced-repetition.md` 执行)

> ⚠️ 上游 `scripts/fsrs/` **只有 Go 源码**(`.gitignore` 忽略产物 `/fsrs`),仓库不带可执行文件,
> 本机亦无 Go 工具链。用之前先做前置检查,跑不通就走**手工排程降级方案**(见阶段七)。

```bash
FSRS_DIR="skills/learning-education/study-skill/scripts/fsrs"
FSRS_BIN="$FSRS_DIR/fsrs"
[ -x "$FSRS_BIN" ] || { command -v go >/dev/null 2>&1 \
  && (cd "$FSRS_DIR" && go build -o fsrs ./cmd/...) \
  || { echo "无 FSRS 二进制且无 Go → 改用手工排程" >&2; exit 6; }; }

FSRS_STORE=复习包/.fsrs/cards.json

"$FSRS_BIN" add "kp-牛顿第二定律-c1" "牛顿第二定律" 5   # 加卡
"$FSRS_BIN" schedule                                    # 今天该复习哪些(due_count + cards)
"$FSRS_BIN" review "kp-牛顿第二定律-c1" 3                # 记录复习结果 1/2/3/4
"$FSRS_BIN" status                                      # 全部卡概览
```

- 每次复习**最多呈现 3 条**、总时长 ≤5 分钟(study-skill 的混合复习模型),别一次性甩给学生几十张卡。
- 复习评分口径:1=完全忘记 2=很难想起 3=想起来了 4=轻松 → 对应 `第 D/S 值更新`,直接照协议传数字。
- 教师用法建议写进 `闪卡导入说明.md`:考前两周把到期卡集中复习;随堂小测答错率高的知识点,
  把对应卡片 `difficulty` 手工调高(改初始值或做一次"Again"评分)。

### 4. 交付形态

- `复习包/题库.json`(全部卡片,含 `source_qid` 映射)
- `复习包/.fsrs/cards.json`(FSRS 状态存储;**仅在 FSRS 二进制可用的环境下产生**)
- `复习包/闪卡排程表.xlsx`(**无 Go / 二进制不可用时的降级产物**:手工排程表,见阶段七降级方案)
- `闪卡导入说明.md`(怎么用命令、怎么读 `schedule` 输出、怎么调难度;走降级方案时注明「按 FSRS 口径手工排程」)

## 与 exam-pipeline 的交接协议

`exam-pipeline` 是本技能的**直接下游**(出题 → 审卷 → 评分细则 → 考后分析 → 归档,见 `ROADMAP.md` P0-2)。
本技能**不做**审卷、不做完整评分细则、不做成绩分析——那是它的事。

> **现状说明**:`skills/exam-pipeline/SKILL.md` 目前**尚未创建**(属 ROADMAP 待开发项)。
> 因此本协议的**字段契约先按此定义冻结**:`exam-pipeline` 建成后必须按这些字段消费;
> 在它建成之前,教师按「手工交接」一步自行把文件交付给审卷人。

### 1. 交接时机

`quiz-generator` 的阶段八产出**已通过本技能质量门**的试卷初稿后立即交接,**不要等教师审完再交接**——
审卷本身就是 `exam-pipeline` 的职责,早交接才能早发现问题(题目歧义、覆盖缺口、A/B 不等值)。

### 2. 交接目录结构

```
handoff/
├── manifest.json            # 机器可读的交接清单(字段见下)
├── 试卷A.docx / 试卷B.docx
├── 参考答案与评分要点A.docx / 参考答案与评分要点B.docx
├── 双向细目表.xlsx           # 含 6 个工作表(见「按知识点覆盖出题 §4」)
├── AB卷对照表.xlsx           # 只在有 A/B 卷时
├── 题库.json                 # 全部题目的内部字段(答案、解析、得分点、难度预估)
├── 出题自检报告.md
├── 知识点清单.xlsx
└── 交付说明.md
```

### 3. `manifest.json` 字段契约(**这是交接的核心**)

```json
{
  "schema_version": "1.0",
  "from": "quiz-generator",
  "to": "exam-pipeline",
  "generated_at": "20XX-XX-XX",
  "course": {
    "name": "【待补:课程名】",
    "code": "【待补:课程代码】",
    "credits": null,
    "student_level": "本科高年级",
    "exam_type": "期末",
    "duration_minutes": 120,
    "closed_book": true,
    "calculator_allowed": false
  },
  "papers": [
    {
      "paper_id": "A",
      "file": "试卷A.docx",
      "answer_file": "参考答案与评分要点A.docx",
      "total_score": 100,
      "question_count": 30,
      "estimated_mean_score": 74.5,
      "difficulty_mix": {"易": 0.30, "中": 0.50, "难": 0.20},
      "bloom_distribution": {"识记": 0.20, "理解": 0.30, "应用": 0.30, "分析": 0.20},
      "type_distribution": {"单选": 0.25, "多选": 0.10, "填空": 0.10, "简答": 0.20, "计算": 0.35}
    },
    {
      "paper_id": "B",
      "file": "试卷B.docx",
      "answer_file": "参考答案与评分要点B.docx",
      "total_score": 100,
      "question_count": 30,
      "estimated_mean_score": 74.2,
      "equivalence_check": {
        "checked": true,
        "kp_diff_max_pp": 0.0,
        "bloom_diff_max_pp": 1.2,
        "mean_difficulty_diff": 0.008,
        "score_scheme_identical": true,
        "passed": true
      }
    }
  ],
  "questions": [
    {
      "id": "Q07",
      "paper_id": "A",
      "kp": "牛顿第二定律",
      "kp_level": "A",
      "chapter": "第3章 §3.2",
      "type": "计算",
      "bloom": "应用",
      "score": 12,
      "est_difficulty": 0.60,
      "stem": "题干全文",
      "options": null,
      "answer": "见参考答案",
      "explanation": "解析全文",
      "scoring_points": [
        {"point": "正确写出受力分析式", "score": 4},
        {"point": "代入数值并解出 a=2 m/s²", "score": 5},
        {"point": "单位与方向正确", "score": 3}
      ],
      "common_misconceptions": ["把合力当某一个力", "忘记方向正负号"],
      "source": "教师提供讲义 p.12(内部留档,不写进试卷)",
      "review_status": "待教师审核",
      "needs_rubric": true
    }
  ],
  "flags_for_downstream": [
    {"question_id": "Q18", "flag": "主观题需完整评分细则(等级描述 + 标竿样卷)"},
    {"question_id": "Q04", "flag": "干扰项来源为学科公认误解,缺教师本班错例,请审卷时确认"},
    {"question_id": null, "flag": "角动量守恒(C级)仅 1 题,请确认是否纳入考试范围"}
  ],
  "prompts_for_teacher": [
    "全部题目须逐题审核后方可进考场(本包为初稿)",
    "第 6 题无教师提供的本班错例,干扰项基于学科常见误解构造",
    "卷头学校名/课程名为占位,请替换为本校教务处模板"
  ]
}
```

**必须传的字段(一个都不能空,空则显式写 `null` + `flags_for_downstream` 对应条目)**:

| 字段 | 为什么下游必须知道 |
|---|---|
| `questions[].id` | 下游的审卷意见、评分细则、考后逐题分析全靠它对齐 |
| `kp` / `kp_level` / `chapter` | 覆盖度复核与考后"哪个考点没掌握"的分析基础 |
| `type` / `bloom` / `score` | 细目表复核与层次偏差复核 |
| `est_difficulty` | 与考后实测难度 P 对比,做预估偏差校准 |
| `stem` / `options` / `answer` / `explanation` | 审卷(歧义、泄露、唯一性)的输入 |
| `scoring_points` | 下游生成完整评分细则(rubric)的骨架;缺则下游要重做一遍 |
| `common_misconceptions` | 下游做"错因归类"与讲评建议 |
| `source` | **审卷人核验是否照搬教材原题的唯一线索**(内部留档字段) |
| `review_status` | 标记是否已过教师人工审核 |

### 4. `exam-pipeline` 应回传什么(反向契约)

本技能期望下游回传以下内容,用于回流改进题库(教师可手工把文件放回工作目录):

| 回传文件/字段 | 用途 |
|---|---|
| `审卷意见.json`(逐题:`question_id` / 问题类型 / 严重级别 / 修改建议) | 逐题修正后重出;把反复出现的问题类型写进本技能的使用说明 |
| `评分细则A/B.docx`(含等级描述) | 归档;下次出同类主观题时参考等级描述写法 |
| `试卷分析报告.xlsx`(逐题难度 P 实测、区分度 D、分数段分布) | **回填预估偏差**:把实测 P 写入题库 `actual_difficulty` 字段 |
| `淘汰题清单`(D < 0.2 的题) | 从题库中标记淘汰,不再复用 |
| `学生错因归类.md` | 成为下一年该知识点的干扰项来源(第一优先级证据) |

回流后本技能要做的事(可选但强烈建议):把 `actual_difficulty` 与 `est_difficulty` 的偏差统计出来,
写进 `出题自检报告.md` 的「预估校准」小节——这是本技能唯一能让出题越来越准的机制。

### 5. 手工交接(`exam-pipeline` 未装时)

1. 把 `handoff/` 整个目录打包给审卷人(同教研室的另一位教师),并附 `manifest.json` 的 `prompts_for_teacher` 原文。
2. 审卷人按「命题缺陷十查」+ A/B 等价性五要素复核,逐条写意见。
3. **本技能绝不自称已审卷**:没有审卷意见就不能把稿件称为"定稿"。

## 产出物

全部 docx / xlsx 一律走 `skills/office-layer/`,禁止手写 OOXML、禁止用文本框拼表格、禁止只交 Markdown。

| 文件 | 通道 | 内容 |
|---|---|---|
| `试卷A.docx` / `试卷B.docx` | `docx_kit.py md` | 卷头(学校/学年学期/课程名/卷别/时长/总分/闭卷说明/多选评分规则 + 得分栏表格)、题目正文、答题空间 |
| `参考答案与评分要点A/B.docx` | `docx_kit.py md` | 客观题答案 + 逐题解析(含干扰项错因);主观题得分点拆分与扣分口径 |
| `命题说明与审核单.docx` | `docx_kit.py spec` | 命题依据(知识点清单/细目表引用)、层次与难度设计说明、**人工确认位**(`【待教师确认:本卷是否可付印】`) |
| `双向细目表.xlsx` | `xlsx_kit.py build` | 6 个工作表:双向细目表 / 知识点覆盖矩阵 / 题型分布 / 层次分布 / 难度预估(含原生柱状图)/ 答案位置校验 |
| `AB卷对照表.xlsx` | `xlsx_kit.py build` | 逐格对照 A/B 卷题号、分值、难度、差值、是否合格 |
| `题库.json` | 直接写 | 全部题目内部字段(`id/kp/type/bloom/score/est_difficulty/stem/options/answer/explanation/scoring_points/source/…`),含 `【待补:依据出处】` 占位 |
| `知识点清单.xlsx` | `xlsx_kit.py build` | 编号/知识点/章节/重要度/前置/学习成果 |
| `出题自检报告.md` | 直接写 | 脚本原始输出 + 命题缺陷十查逐条结论 + 知识点覆盖率 + 预估校准(有历史数据时) |
| `复习包/题库.json`、`复习包/.fsrs/cards.json`、`复习包/闪卡排程表.xlsx`、`闪卡导入说明.md` | 前两个直接写;排程表走 `xlsx_kit.py build` | 拆好的卡片、FSRS 状态(或降级的手工排程表)、使用说明 |
| `handoff/manifest.json` + 上述文件的副本 | 直接写 | 交 `exam-pipeline` 的机器可读清单 |
| `交付说明.md` | 直接写 | 本次用了哪些默认值、所有 `【待补:…】` / `【待教师确认:…】` 清单、审卷提示 |

**通用卷头模板**(`md` 通道用 Markdown 表格写,教师可对照本校模板替换):

```markdown
# 【待补:学校名】20XX—20XX学年第一学期
## 《【待补:课程名】》期末考试试卷(A卷)

考试形式:闭卷  考试时长:120 分钟  满分:100 分
(多项选择题评分规则:全部选对得满分,漏选得一半分,多选或错选不得分)

| 题号 | 一 | 二 | 三 | 四 | 五 | 总分 |
|---|---|---|---|---|---|---|
| 满分 | 20 | 10 | 20 | 20 | 30 | 100 |
| 得分 |  |  |  |  |  |  |

**考生须知**:请将答案写在答题纸指定位置;计算题需写出必要步骤,只写答案不得分。
```

> 试卷页眉页脚、密封线、装订线属学校模板差异,本层**不替你猜**:
> 用 `docx_kit.py spec` 出《命题说明与审核单》承载需要页眉页脚与人工确认位的部分,
> 试卷正文用 `md` 通道出,并在交付说明里写「卷头为通用模板,请对照贵校教务处模板调整」。

## 红线

1. **题干不得直接照搬教材原题。** 教材例题、课后习题、往年试卷的题干/数据/选项都必须改写:
   换情境、换数值、换问法。若确实需要引用,须注明来源并取得教师确认。
   `题库.json` 的 `source` 字段是审卷人核验这一点的唯一线索,**不得为空或伪造**。
2. **不虚构引用来源。** 案例来源、文献、政策条文、课程标准编号、教材页码一律不得编造。
   教师给了才写;没给留 `【待补:依据出处】`。案例题一律标注
   `【案例来源:教师提供 / 公开报道改编 / 为教学目的拟制】`,**不得写不存在的来源**。
3. **生成的题目必须由教师审核后方可使用。** 本技能产出的是**待审稿**。
   题目、答案、评分要点都可能存在学科性错误,**未经教师逐题审核不得印卷、不得发给学生**。
   每份产出的交付说明里必须有这句话。
4. **不生成学生数据。** 不得虚构班级名单、成绩、错题统计、学情分布。
   没有教师提供的真实数据时,干扰项只能基于「学科公认的常见误解」构造,并显式标注缺教师本班错例。
5. **不替教师做判断性结论。** 不写「这套卷子难度合适」「学生应该能考到 80 分」这类结论性表述;
   只给测算值与偏差,判断与确认留给教师(人工确认位 `【待教师确认:…】`)。
6. **不泄露答案到试卷面。** 试卷 docx 内不得残留答案字母、解析、得分点、干扰项设计说明。
   答案与解析只出现在《参考答案》文件里。交付前用 `docx_kit.py inspect` 读回核对。
7. **不虚报质量门结论。** `quiz_audit.py` 的原始输出必须留档;有未处理问题项时**不得交付**,
   也不得把「未通过」写成「基本通过」。
8. **A/B 卷不得以「同一套题换序」冒充。** 见「A/B 卷生成」的禁止条款。
9. **只抄袭方法论,不抄袭文本。** ibook 系列底座(`question-writing` 等)的上游仓库无 LICENSE 文件(见 `THIRD_PARTY_NOTICES.md`),
   禁止把其英文原文、模板、代码整段搬进交付物;一切交付物用中文重写。
10. **敏感数据本地处理。** 如果教师提供了含学号/姓名/成绩的错例材料,只在本机处理,
    不写入交付物、不外传;任务结束后提醒教师删除中间文件。

## 自检清单

交付前逐项过,**任一项不通过就不交付**。

**intake 与依据**
- [ ] 13 项前置信息一次性问完(不是边做边问)
- [ ] 知识点清单已回读给教师确认,每条能指向材料中的具体位置
- [ ] 用了默认值的项目都在交付说明里逐条列出

**规划**
- [ ] 双向细目表各格分值之和 = 卷面总分
- [ ] 认知层次实际占比与 intake 目标偏差 ≤ 5pp
- [ ] A 级知识点覆盖率 = 100%;未覆盖知识点已逐条说明理由
- [ ] 全卷作答时间 ≤ 考试时长 × 85%
- [ ] 全卷预计平均分落在 intake 目标分 ±5 分内(且目标分按 §4 卷型口径取 75±5 或 65±5,非主观题卷型硬套 75)
- [ ] 易:中:难比例符合要求(默认 3:5:2)

**命题质量**
- [ ] 每个干扰项都能说出对应的一条学生常见错误(或已标注 `【待教师补充:…】`)
- [ ] 无「以上都对/都不对」凑数项;无绝对化词送分项
- [ ] 正确项长度与干扰项均值之比 ≤1.4(脚本已核)
- [ ] 无否定式题干(或已加粗提示并在卷头说明)
- [ ] 选项语法平行、互斥、无同义项
- [ ] 全卷无跨题泄露;答案未出现在题干或别题中
- [ ] 每道主观题至少 2 个可独立判分的得分点,得分点分值合计 = 该题满分
- [ ] 术语与符号全卷统一
- [ ] 无任何题目照搬教材原题;每题 `source` 已填或显式占位

**质量门**
- [ ] `quiz_audit.py` 问题清单 = 0 条,原始输出已留档
- [ ] 「命题缺陷十查」逐条留痕(已查无问题 / 已修正 + 说明)
- [ ] 答案位置 A/B/C/D 各 25%±5%(多选与主观题不计入)

**A/B 卷(如适用)**
- [ ] 等价性五要素逐项有实测差值,全部在容差内
- [ ] AB 卷对照表无空格,行数 = 细目表格数
- [ ] 两卷无「换皮题」,人工逐题复核完成并留痕
- [ ] 两卷卷头都标注卷别与「不得同场混用不同卷别」

**闪卡(如适用)**
- [ ] 一张卡只问一件事;正面不泄露答案;背面 20 秒可读完
- [ ] 判断题卡已改写为提问式,未保留原判断句
- [ ] `difficulty` 由 `est_difficulty` 映射,不是全卡同值
- [ ] `fsrs status` 能列出全部卡片;每张卡有 `source_qid` 关联
- [ ] 若 FSRS 二进制不可用:已走降级方案出 `复习包/闪卡排程表.xlsx`,且交付说明明确写了「按 FSRS 口径手工排程,非自动调度」

**产出**
- [ ] 所有 docx/xlsx 由 `skills/office-layer/` 生成,且都跑过 `inspect` 读回核对
- [ ] 试卷 docx 内无答案、无解析、无得分点残留
- [ ] 题号连续无跳号;跨页未把题目劈成两半;主观题留足作答空间
- [ ] 三类占位(`【待补:…】` / `【待教师确认:…】` / `【待补:依据出处】`)已全部列进交付说明
- [ ] 交付说明含「本文件为出题初稿,全部题目须经教师逐题审核后方可进考场」

**交接**
- [ ] `handoff/manifest.json` 字段齐全,`questions` 条数 = 细目表题数
- [ ] 每个交接文件路径存在且非空
- [ ] `flags_for_downstream` 已列出所有需要下游注意的项(缺指标、需完整 rubric、覆盖疑问)
- [ ] 未自称「已审卷」「定稿」

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.