zekainie/exam-tutor
> 按章节惰性加载授课:每次只读当前阶段的一个 wiki 章节,用生活隐喻讲概念、解剖公式;重点题固定走 题面图→问题→读图量→公式→演算→答案详解→溯源七步,画图题先运行算法。用于讲懂当前章或老师勾出的重点题。
npx skills add https://github.com/ZeKaiNie/universal-examprep-skill --skill exam-tutor
Teach exactly one current wiki chapter, using metaphors and formula dissection. In zero-basic mode, explain every linked key question with the fixed seven-step walkthrough. Run algorithms before rendering diagrams. This skill teaches; exam-quiz alone quizzes and scores.
Use when exam-cram routes the current phase to teaching, or the student asks to learn the current chapter, derive a formula, or explain a key question.
processing_mode=lightweight: one schema-3 visually accepted current-page batchfrom .lightweight/session.json plus its original pages and declared-scope
prompt/answer component assets; no compiled wiki is required.
references/wiki/chN_*.md: the one current chapter; never read the whole wiki.references/teaching_examples.json: optional examples, read only through the chapter-filtering CLI below; never an answer source.study_state.json: progress source of truth when present; otherwise the generated study_progress.md compatibility view.study_state.json.processing_mode first. Inlightweight, call lightweight_session.py status, plan only the current
source/page range if it is not already planned, visually inspect those pages,
and import the generic item/component manifest with record-visual; teach only a
schema-3 visual_ready batch. A schema-2 visual_ready receipt is quarantined
read-only: auditably abandon it and plan a new attempt, never teach from or
silently upgrade it. While still planned, keep register-answer-dependency
additive; use set-answer-dependency --reason to replace/narrow exact answer
pages and remove-answer-dependency --reason to remove them. Do not call
ingestion/OCR, preload later pages, or require a
wiki. In full, read exactly one current references/wiki/chN_*.md. A missing
full-mode file means abstain, name it, and never improvise. If full-mode teaching
examples exist, run `python "${CLAUDE_SKILL_DIR}/scripts/list_teaching_examples.py"
--workspace <ws> --chapter <N> --json` and use only its returned slice. When the
full-mode effective cadence below is step_by_step, use --next-pending instead
of loading the whole chapter example slice. A nonzero
exit is an invalid/unreadable inventory, not “no examples”; report it.
$...$ or $$...$$; never leave raw \frac, \sum, or other TeX as the final reading view.Full-mode pacing: read the stored preference plus its reported effective and
dormant state. study_state.json.preferences.interaction_style stores only
batch|step_by_step; missing legacy state means batch. This optional preference
is independent from processing_mode, artifact_mode, and
answer_explanation_mode, and is not a fourth required startup choice. Persist an
explicit change only with `update_progress.py --workspace <ws> set
--interaction-style <batch|step_by_step>` (or the strictly validated canonical
--pref interaction_style=...). It never changes the lightweight page-batch route.
This option applies only to full-mode teaching_examples.json items. It does not
claim coverage of the chapter bank, typed question units, or the lightweight
page-batch route.
batch: use the normal full-mode flow. A truepreferences.no_questions=true or any non-full processing mode makes a stored
step_by_step choice dormant without overwriting it. A stored batch choice
remains ordinary batch cadence.
step_by_step: call `list_teaching_examples.py --workspace <ws>--chapter <N> --next-pending --json. It requires processing_mode=full`,
no_questions=false, exact current_phase, and valid scoped manifest/state data.
It reads the manifest, state, notebook bindings, and baseline within one
consistent workspace lock, then returns the first manifest-ordered pending item.
A missing manifest, malformed state, or nonzero selector exit blocks the pacing
decision; report it and do not guess another item. Two bindings may not share one
notebook_ref. Only a missing notebook entry or anchor/marker/hash/revision drift
may return to pending with bounded stable diagnostics. Link/reparse topology,
non-directory/non-regular targets, path escape, invalid UTF-8, an unterminated
fence, parse/block corruption, schema/scope/baseline damage, duplicate evidence,
and unexpected_evidence are fatal.
Unbound IDs already present in phase_evidence[N].teaching_examples are legal
batch/legacy history rather than corrupt step evidence; any ID with a
teaching_example_bindings record must pass its live notebook-block and
manifest-item hash checks regardless of the currently selected cadence. Teach
exactly that one item this turn, but complete all seven blocks below; never split
one walkthrough across turns. Do not infer progress from notebook presence,
language-specific prose, or “I understand” / Continue. If next=null,
teaching_example_roster_exhausted=true means only that this full teaching roster
has no pending item, including an empty roster; it never completes the chapter or
bypasses Guide, bank, typed-unit, asset, checkpoint, or phase gates.
A structurally sound current roster with either a stale manifest/notebook binding
or an append-only newly added item is a named usable_with_gaps mount warning so
manifest-order re-teaching remains legal. Structural/scope/baseline corruption
stays blocked; the old Guide/completion receipt remains ineligible. Teaching IDs
use the shared 1–200-character Guide-safe Unicode contract; keep an incompatible
source-facing label in source/title metadata instead of changing a stable ID. If
the ID alone produces an empty Markdown slug, the notebook entry needs a
descriptive title. Every retained baseline ID must have a current teaching
snapshot in the same canonical chapter under exact policy=append_only; a
quiz-only copy cannot substitute.
For each active question to be explained:
考点 in plain language. Never jump from the prompt to ④.⑤ 逐步演算(⚠️ AI生成答案,非老师/教材提供).Immediately after ⑦, end with one source line in the active language: 题目来源:<文件/页/source_type>|答案来源:<材料位置/老师·教材提供/AI 推导(无教材答案)>|<canonical label> or Question source: <file/page/source_type> | Answer source: <...> | <label>. Missing metadata says 「来源未知」 / Source unknown. The label is exactly one canonical sentence from docs/language-policy.md: 🟢 来自资料; 🟡 AI补充,可能与你老师讲的不完全一致; or ⚠️ AI生成答案,非老师/教材提供 (and its English counterpart). With no material answer, both ⑤ and this line carry the full ⚠️ sentence.
The seven blocks plus source line are the complete default. 易错点 / 3分钟速记 / 现在轮到你 appear only when requested or stored in 讲解模板; legacy 【考点拆解】 and 【标准答题模板/步骤】 are already covered by ② and ④⑤ and must not be duplicated.
Honor a stored 讲解模板 preference. If absent and the tier is not ≤1天, ask once for 七步精讲 (STEM default) or 文科变体, then persist it with python "${CLAUDE_SKILL_DIR}/scripts/update_progress.py" --workspace <ws> set --pref 讲解模板=<七步精讲|文科变体>. In the ≤1天 tier, asking is forbidden: immediately use 七步精讲 for STEM or 文科变体 for clear non-STEM and persist that inferred default silently. Neither variant may remove a block or source line. If state is absent and Python works, initialize it first; only a true no-Python fallback may write the generated view.
Persist before replying: pipe the complete walkthrough to python "${CLAUDE_SKILL_DIR}/scripts/notebook.py" --workspace <ws> add-entry --chapter <N> --type walkthrough --id <qid> --title <gist>. Omit --lang to inherit the canonical zh|en|bilingual value from study_state.json, or pass that same value explicitly; never store a bilingual body under a fake zh override. Quiz/teaching/notebook/Guide IDs share the safe-Unicode 1–200-character contract; if the ID alone generates an empty Markdown slug, supply a descriptive title. The same chapter/id replaces in place and rebuilds notebook/index.md. For effective full-mode step_by_step, add --teaching-example; this writes a reserved ID-bound marker. After that succeeds, use only update_progress.py --workspace <ws> record-taught-example --id <qid> --notebook-ref notebook/chNN.md#<anchor>. The command validates full/effective-step mode, the current first-pending manifest item, exact anchor, walkthrough type, matching ID, and marker, then atomically stores the ID/notebook evidence plus exact teaching_example_bindings fields id, notebook_ref, notebook_block_sha256, and manifest_item_sha256. Unbound IDs remain legal batch history; a bound event must continue to pass live notebook/manifest validation after cadence changes. Never replace this with two loose record-phase-evidence writes. Acknowledgement/Continue is routing input only, never completion evidence. Guide notebook publication must leave a live-valid bound marked block unchanged; it fails closed rather than rewriting a stale binding or a marked block without a valid binding. Then reply with a 3–5 line digest and the language-pack link. In effective step_by_step, append the active-language continuation wording after the digest, outside the persisted walkthrough; under le1d it must be a non-reflective continue/reteach prompt, and an unstored style must not trigger a preference question. In bilingual mode, render the Chinese continuation line followed by its pure-English > EN: mirror; either language's Continue command routes one next turn and never creates duplicate evidence. If either write fails, report it and do not claim the item complete; a failed notebook write must be followed by the full chat content. File-less clients use chat plus a text breakpoint.
requires_assets=true or maybe_requires_assets=true, render every question-side question_context / figure / diagram / table asset, labelled 题面图 or Question-side asset. Only afterward may solution/review show official answer_context / worked_solution, labelled 答案图 or Answer-side asset. Preserve but do not display or teach from student_attempt; it is neither prompt nor official/material answer evidence. Treat its physical path as globally tainted across quiz, teaching, and all content units, folding safe slash/backslash aliases and Windows case aliases; never display an official declaration of that path. Reject same-item prompt/answer reuse. Cross-item official prompt/answer reuse without an attempt is legal, and distinct official plus attempt paths remain usable. Missing/unreadable files block a structured workspace and return to validation/exam-ingest; a UI that cannot render the existing image must skip the item. A path is not an image. Prefer python <package-root>/scripts/show_question_assets.py --workspace <ws> --id <qid> --lang <zh|en>; exit 1 means skip. Apply the same gate to stub / page_reference prompts.In lightweight schema 3, apply this rule to generic components rather than only figure questions. Use the item's text|figure|mixed kind honestly; show every prompt component required to understand the target before teaching, including declared shared context, and never display an answer component until solution/review. A detail call may combine prompt components only for the same target. Trust a component only after its separate crop review detects exactly allowed_detected_item_ids (target plus all declared contexts, or a declared non-empty context-only crop) with no unrelated content or student attempt. A text-only prompt may use a cross-file official answer without being relabelled as a figure item; only official_solution parent pages may provide answer components, and every registered official page must be covered.
confusion-tracker and python "${CLAUDE_SKILL_DIR}/scripts/update_progress.py" --workspace <ws> add-confusion; initialize missing state when Python works.record-phase-evidence for wiki, visual, notebook, and bank checkpoint evidence (--kind checkpoint --ref <qid> --outcome passed|wrong|skipped). Batch-mode full teaching examples may use its ordinary teaching-example kind, producing legitimate unbound history; effective full step_by_step must instead use the marker-bound record-taught-example path above. Bound history remains live-validated after switching back to batch. Every ID retained by teaching_baseline.json must have a current teaching_examples.json snapshot; a matching quiz item alone cannot satisfy or exhaust the teaching roster. verified requires at least two handled bank items and one pass. set --phase <N> is only explicit navigation/repair, never completion.In lightweight, never invoke exam-study-guide; after persisting the full
walkthrough and updating progress, bind the batch with
lightweight_session.py mark-taught --batch-id <id> --notebook-entry <path> --taught-item-ids <exact-comma-separated-IDs-from-the-visual-receipt>. The
inspected page list is context, not proof that every item on those pages was
taught; close only the exact item IDs enumerated during visual review.
Plan the next pages only when the learner reaches them. Without a pre-existing
standard bank, no verified checkpoint exists and completion is capped at
covered_unverified. In full, after all current-chapter material has persisted
walkthroughs, invoke exam-study-guide to build, validate, and import the
profile=full notebook/chNN.guide.json. Its de-duplicated teaching-example +
all-bank + typed-question denominator is a coverage gate, with gradable=false
bank records retained as teaching-only Guide content; it is not proof of semantic
recall. Effective missing/unknown artifact_mode is chat: typed import is
enough before complete-phase --status covered_unverified|verified, with no
HTML/PDF. Standing visual must also select the PDF route, render, bind receipts,
accept every page, and reach artifact_ready=ready. A one-shot artifact request
temporarily overrides chat without changing the standing value. Never infer a
subscription or install dependencies silently. Language changes stale the
manifest/artifact: route to exam-study-guide for relocalization, refreshed
claims/receipt, re-import, rerender, and repeat QA. A request for “all examples”
remains profile=full under le1d; time pressure may shorten prose, not omit
required items or language blocks.
≤1天: no opening preference or reflective follow-up; teach now. This does not ban bank-backed drills or checkpoints. Explicit 「不要出题 / 不要问我」 persists no_questions=true, emits no interactive question, and caps completion at covered_unverified.1-3天: occasionally recheck earlier difficult/confused points and reteach forgotten ones.3-7天: add taught points to the knowledge window; ask whether an out-of-window point is remembered before restoring it.>7天: test an out-of-window point with its linked hard bank item; pass → window-set-status ... --status 已实测, fail → reteach. A point/index locator is required; add chapter for ambiguous names.step_by_step, append the language-pack continuation prompt after the digest, never inside the persisted walkthrough. It routes the next turn only and never certifies understanding, creates evidence, or bypasses completion gates. Under le1d, use a non-reflective continue/reteach prompt and never ask for an unstored cadence.update_progress.py set / set-check; delegate all practice and scoring to bank-only exam-quiz.study_state.json.language: pure Simplified Chinese for zh, pure English for en, and blockwise zh then > EN: for bilingual. Original source quotations may keep their language only when labelled; generated prose may not.Load before student-visible output:
中文 → ../../locales/zh/skills/exam-tutor.mdEnglish → ../../locales/en/skills/exam-tutor.md双语 → compose both blockwise, zh then > EN:, under docs/language-policy.mdDisplay aliases are normalized to zh, en, or bilingual; unset language defaults to English unless the opening is Chinese.
study_state.json is the source of truth. Write it only through python "${CLAUDE_SKILL_DIR}/scripts/update_progress.py" --workspace <ws> ...; study_progress.md is generated. Fail writes loudly. If study_state.json is absent and Python works, run init before any write; hand-maintain Markdown only when Python truly cannot run.source_type; announce before overriding it: 「⚠️ 临时覆盖你的 <scope> 范围偏好」 / ⚠️ Temporarily overriding your <scope> scope preference. Use scripts/select_questions.py.requires_assets=true, maybe_requires_assets=true, stub, or page_reference question whose prompt image cannot be shown must not be taught as complete.interaction_style is a full-mode teaching-manifest cadence only. Its stored value is exactly batch|step_by_step, with missing state treated as batch; step mode is effective only in full with no_questions=false, otherwise the stored step choice is dormant and effective cadence is batch. Stable item IDs mean a reply-language change does not automatically requeue already evidenced items; request an explicit reteach. Never infer completion from notebook presence, language-specific prose, or a Continue acknowledgement. The selector takes a consistent workspace-locked snapshot and returns manifest order, but it is not a pause/acknowledgement or reservation ledger, so concurrent tutors may still select the same pending item.Take zekainie/exam-tutor from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.