FERPA去标识化
chaz-clark2026-10-25查看 1795复制 305
用于去标识化 / 再标识化工作流——构建课程级去标识主表、在内容到达 LLM 之前对提交物或成绩册(docx/pdf/xlsx/jupyter/databricks/text/comments)进行去标识化、将带键结果再标识回学生,以及扫描姓名泄露。在准备学生产物以供 AI 处理或将带键结果转回具名报告时加载此项。FERPA 的*纪律*(绝不读取
📘如何使用这个技能
- 1复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
- 2打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
- 3粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
- 4直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景
💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。
SKILL.md3929 chars
---
name: ferpa-deid
description: Use for the de-identification / re-identification WORKFLOW — building the course-wide de-id master, de-identifying submissions or a gradebook (docx/pdf/xlsx/jupyter/databricks/text/comments) before anything reaches the LLM, re-identifying keyed results back to students, and scanning for name leaks. Load this when preparing student artifacts for AI processing or turning keyed results back into a named report. The FERPA *discipline* (never read Zone-2 files) is constitutional and always applies; this skill is the *how* of the de-id machinery.
---
# FERPA de-identification / re-identification
The machinery that lets student work be processed by an LLM without a name ever
reaching cloud context: strip identity → opaque keys → process → map keys back
locally.
> The **constitution** (AGENTS.md) is the law: the name-bearing files
> (`.deid_master.csv`, `.keymap.json`, `.known_names.txt`, `.review.csv`,
> `submissions_raw/`, `feedback/_grader*.csv`) are **FERPA Zone-2** and are **never**
> read or displayed — verify with `wc -l`/`ls`, never `cat`/`head`/`grep`. This
> skill runs the de-id tools; it never bypasses that rule.
## The two-zone flow
```
raw submissions (names) ──deidentify──▶ opaque keys ──▶ LLM / analysis
▲ │
└────────── reidentify (BY KEY, local) ◀──────────────┘
```
- **Zone 1 (cloud-safe):** de-identified keys + grades. Fine for the LLM.
- **Zone 2 (local only, gitignored):** the keymap/master that links keys ↔ names.
## Building the master
`build_deid_master.py` builds the course-wide `.deid_master.csv` — **one row per
student**, keyed by `user_id`, with a stable opaque `deid_code = sha256(user_id)[:6]`.
It dedups multi-section students (a student in S1+S2 is otherwise returned twice) and
auto-derives `.known_names.txt` (the scrub roster). Run `--force` to refresh from
current enrollment. This is the identity surface every keyed tool and accommodation
consumes.
## De-identifying artifacts (before the LLM)
`grader_fetch.py` de-identifies submissions automatically, dispatching to the right
format adapter. The standalone adapters exist for direct/one-off use:
| Artifact | Tool |
|---|---|
| Word docs | `grader_deidentify_docx.py` |
| PDFs | `grader_deidentify_pdf.py` |
| Excel | `grader_deidentify_xlsx.py` |
| Jupyter notebooks | `grader_deidentify_jupyter.py` |
| Databricks exports | `grader_deidentify_databricks.py` |
| Plain text | `grader_deidentify_text.py` |
| Canvas submission comments | `grader_deidentify_comments.py` |
| A gradebook export | `grader_deidentify_gradebook.py` |
## Re-identifying results (BY KEY — never by sort order)
- `grader_reidentify.py` maps `key → user_id` via `.keymap.json`, and is
**duplicate-aware** (`user_id → [keys]`): one student legitimately has many keys
across submission batches (e.g. `final-review_*` + `fpr_*`). **Never** map by row
position / sort order — that misattributes results. If two batches share user_ids,
that's expected; the keymap disambiguates.
- `grader_reidentify_gradebook.py` re-identifies a de-identified gradebook.
- Re-identified output is Zone-2 — write it outside any cloud-synced or git-tracked
path (e.g. `~/Downloads/`), never back into the repo.
## Verifying no leak
`grader_name_leak_check.py` scans keyed/de-identified artifacts for any name that
slipped through the scrub (against `.known_names.txt`). Run it before handing
de-identified material to the LLM if you're unsure the scrub was complete.
## Quick command map
| Ask | Command |
|---|---|
| "Rebuild the de-id master / student list" | `build_deid_master.py --force` |
| "De-identify these submissions" | (usually automatic via `grader_fetch.py`) |
| "Turn the keyed results back into names" | `grader_reidentify.py --challenge-dir grading/<name>` |
| "Check nothing leaked a name" | `grader_name_leak_check.py …` |