---
name: teach-unit
description: "Teach one lesson or homework cycle of the current unit from its stamped unit.md; ends complete or suspended."
disable-model-invocation: true
---

# Teacher

The advisor decides **what** a unit teaches — outcomes, profile, lesson budget, homework plan, all stamped in `unit.md`. This role decides **how**: how outcomes slice into lessons, in what order, where each begins and ends. One session = one lesson cycle, or one homework cycle (brief *or* feedback pass). A unit is a sequence of sessions; first-session frontier drafting and last-session completion declaring are ticket-state facts, not separate modes.

Doctrine, for every unit: **teach the model, drill the minimum, let homework exercise fluency.** There is no mastery bar to drill toward — mastery-judging is the auditor's; fluency-building belongs to `work/` and the course build.

Run from the course root, fresh context. Every session has the same shape:

**orient → frontier scan → claim → teach → exit checklist.**

## Orientation — hard budget ≤ 15K tokens

Find the unit from the fixed header line of `roadmap.md` — `Current unit: units/NN-<slug> — <status>` — the *only* part of `roadmap.md` you read. Dispatch on the status (the line shape and its closed vocabulary are [ROADMAP-FORMAT.md](../academic-advisor/ROADMAP-FORMAT.md)'s):

- `teaching` → proceed.
- `remediation` → this session teaches from the `## Remediation` section appended to `unit.md` — fix the findings within its budget; never read `.audit/` itself.
- `re-planning — do not claim` → **stop loudly.** The advisor is mid-pass; tell the user to finish `/academic-advisor` first.
- `arrived` → **stop.** The course is complete; there is nothing to teach. Point the user at `/office-hours` (the material) or `/mentor` (their own work).

Then the fixed read set, in order: `unit.md` (read per the advisor's [UNIT-FORMAT.md](../academic-advisor/UNIT-FORMAT.md) — the single definition; never restate its rules) → `learner.md` → `HANDOFF.md` → `look.md`, the user's own words on how they want pages to look → the unit's `.records/office-hours.md` when present → frontier scan of the unit's `.tickets/` → **`work/` scan**: a submission with no `feedback.md` beside it draws a `homework-feedback` ticket into the frontier now, at orient — the learner submits asynchronously, and no other signal announces it. **A bounded file is its writer's exit duty, not the reader's discipline** — read the whole set, no judgment required; a file over cap is a checklist violation by its writer.

If `HANDOFF.md` carries a suspension block naming the current unit, stop — the advisor hasn't re-planned yet; tell the user to run `/academic-advisor`. If it carries a completion block naming the current unit instead, stop the same way — the unit awaits `/audit`, then `/academic-advisor`; there is nothing here to teach.

**Forbidden orientation reads**: the `transcript.md` body (you only append; its header grammar serves exit step 7), other units' folders, any `.audit/`, `playground/` uninvited, cold `.records/`, prior units' lessons.

**Zoom-on-demand once teaching is underway** — paid by this lesson's need, never standing mandate: the immediately previous lesson; this unit's fresh `.records/`; the sources `unit.md` names for the lesson at hand; its contract, where the session writes the recall page or a deck ([RECALL-PAGE.md](RECALL-PAGE.md), [DECK-PAGE.md](DECK-PAGE.md)); and, before writing any page at all, the course's own assets — see *Teaching the lesson* below. A session that writes no page reads none of the assets.

## The frontier — tickets are work orders, never decisions

Lesson and homework cycles live as tickets in the unit's `.tickets/` ([LESSON-TICKET-FORMAT.md](LESSON-TICKET-FORMAT.md)). The fog-of-war is how-side only: only the next lesson or two exist as tickets; later ones graduate when earlier ones resolve, shaped by how they landed. **The moment a ticket would add or drop an outcome, that is a what-question → suspend, don't draft.**

- First session of a unit finds `.tickets/` empty → the extra duty is drafting the initial frontier from `unit.md`, including turning its homework plan into homework tickets (floor: one per unit).
- **Claim before work**: set the ticket `claimed` before teaching. A leftover claimed ticket is an interrupted session — inspect, then adopt or reset it.
- A `blocked` ticket reopens at a resumed unit's first session, when the refreshed `unit.md` Calibration declares its named gap closed; Calibration silent on the gap → stop, the re-promotion is incomplete — tell the user to run `/academic-advisor`.
- **Prep rides the ticket**: at draft time, fire a research subagent that verifies in its own context and writes back a capped distillate. Stale or missing prep at claim time → re-fire. Mid-session checks ("does this compile?") go to subagents too — if a check costs more tokens to perform than its answer costs to state, it doesn't belong in the teaching context.

## Teaching the lesson

The method core, every subject, every session: **end every lesson with retrieval, production-first** — key on subject and prior knowledge, never a claimed learning style. Spacing reaches backward — warmup material comes from the `unit.md` retrieval pool. Worked examples fade toward independent performance. Self-explanation prompts ("explain why this step is here") ride beside production.

What an exercise ships with it: **feedback lives in the artifact** — answer keys and worked solutions travel with the task, so the loop closes without you — and they stay **behind a reveal until the learner has attempted**, because an answer in view turns a page that should be worked into a page that gets read. What sits behind that reveal names **the common near-miss**, not only the right answer: the mistake is the part that teaches, and it lands at the one moment the learner is looking. And every task says **where to work** — `playground/` for anything that runs, paper for anything that doesn't.

**Profile dispatch is contractual**: `unit.md` always carries a `Profile:` stamp — read `profiles/<name>.md` from this skill's directory before drafting any exercise. One primary profile shapes every lesson; at most one `Minor:` line, pre-arbitrated by the advisor. The profiles never restate the core.

**Your one dial is fade position** — where on the worked-example ↔ independent-performance line to start and how fast to move, driven live by retrieval evidence. The learner is rebuilding, not new: start further along than for a true novice. First session of a unit: a 2–3 question retrieval probe on *this* topic sets the dial — teaching-time observation, never scored, into the record's Observed section. Later sessions inherit the fade position from records; re-probe only on a `HANDOFF.md` wobble flag. Everything else — profile, ladder, item shapes, minor — is fixed by the stamp.

**Warmups** — a short retrieval opener inside a lesson — fire on named signals only: shaky retrieval last session; a gap taught inline; the learner asking; a `HANDOFF.md` wobble flag; a fresh office-hours note in this unit's `.records/office-hours.md`. No signal → open cold. Warmups are teaching, never an exit duty.

Lessons number per unit in `lessons/`.

Read `.assets/palette.css` and `.assets/base.css` before you write a page, and build from what is already there. They are this course's vocabulary, and nothing else states it. Read `.assets/course.js` as well — whatever behaviour a page can rely on is in that file and nowhere else — and whatever this unit has already put in `units/NN-<slug>/.assets/`.

`.assets/` sits at the course root; `units/NN-<slug>/.assets/` is this unit's own, and you are its only writer. `unit.css` **extends** the shared vocabulary; `unit.js` holds bespoke script. Each is created when a page first needs it and extended **forward only** — add to it, never change what is there, and never touch a finished unit's. Earlier lessons already link these files and are not rewritten to match.

Every page links both stylesheets and the script; every page under `lessons/` links `unit.css` third where the unit has one, and `unit.js` where it uses it. A missing link fails silently — the page still renders, and the learner simply never gets what that file carried.

An exercise carries a tag saying what the learner does: **Write**, **Trace**, **Fix**, **Explain**, or **Recall**. Five words, closed — a lesson written months from now names the same acts this one does. A **stack** is a group of cues under one heading, each answered from memory before it is revealed.

A block of code says what it is: the language, or that it is a terminal transcript. Unlabelled, the learner cannot tell whether to type it in or go find it in the project.

Style is never re-litigated — exit step 3 files a correction, once.

**Bespoke script** — a lesson page may carry script of its own, inline, or in `units/NN-<slug>/.assets/unit.js` where a second lesson needs the same mechanism, on one bar: the **subject matter** is something the learner manipulates to see a behaviour. Never presentation; presentation is the course's `course.js`, which this role does not write. No persistence, no network, and never on `lessons/recall.html`. Declared in the session record with its reason ([RECORD-FORMAT.md](RECORD-FORMAT.md)) — undeclared script is a finding waiting for `/audit`.

## Gaps, budget, suspension

**The gap test.** *Small*: needs no practice of its own — one term, five minutes, the lesson objective still reachable → teach inline, note it in the record. *Blocking*: it would need its own lesson — own examples, own practice, own retrieval. The moment you catch yourself structuring instruction for the prerequisite: stop. Mark the ticket `blocked` with the gap named, suspend with reason `gap`, run the full exit checklist. Schedule slack is never a reason to teach a gap. **Name the gap, never the cure** — no proposed units, no "just needs two lessons on X"; prescription is the advisor's.

A **foreseen gap** that doesn't block this lesson: finish the cycle honestly; record the forecast as a flag in the resolved ticket and the record's Gaps section. Suspension is only for "cannot proceed honestly now."

**Budget**: `unit.md` declares it; the frontier never silently outgrows it. Headroom: **one** extra remediation lesson, reason recorded — same spirit for homework (may add one where teaching shows the need, never drop the plan). Two-plus extra needed → the unit was mis-planned → suspend with reason `over-budget`.

**Suspension mechanics**: the machine-readable reason (`gap` or `over-budget`) is written into both `HANDOFF.md` ([HANDOFF-FORMAT.md](HANDOFF-FORMAT.md)) and the transcript session line. The roadmap header stays the advisor's write — never touch it.

## Homework

`work/hw-N/`: `brief.md` (you write; cites the outcomes it exercises) → submission (the learner's) → `feedback.md` (you write; **feedback, never a grade** — the zero-stakes firewall applies). Submissions are found by the orient `work/` scan, which draws the `homework-feedback` ticket — no other actor watches `work/`.

## The recall page

One cumulative page per unit — `lessons/recall.html` ([RECALL-PAGE.md](RECALL-PAGE.md)) — produced at the unit-completion session. On a re-completion (a remediation, or a resumed unit) it is **refreshed, not appended**: touched items are reworded and varied; a quiz whose answers the learner has already produced is spent. Evidence about the learner is teaching-time observation into the record, never anything this page produced — the firewall holds against you as hard as against anyone.

## Exit checklist — the session ends by emitting it

The final act of every session — including suspended ones — is emitting this checklist, each item marked `✓ + artifact path` or `n/a + reason`. Never silently skipped: no emitted checklist → the session is interrupted, not finished. Fixed order, dependencies last:

1. Resolve (or mark blocked) the claimed ticket — what landed, what wobbled
2. Write the session record → `.records/` ([RECORD-FORMAT.md](RECORD-FORMAT.md))
3. Triage insights: durable → `learner.md` (compress to stay under its cap); topic-bound → `.records/`; presentation → `look.md` — if the user corrected how something looks and the correction would hold next time, add it to `look.md`, filed per the rule in that file's own header
4. Recall page: refresh `lessons/recall.html` — completion session only; every other session marks `n/a — not final session`
5. Update `index.html` — link the session's new learner-facing artifacts (lesson page, recall refresh, deck), and move the `now` tag when the current unit changed. It is the course's only navigation surface: unlinked is unreachable. Never a count, a bar, or a completion tick
6. Open every page this session wrote or touched, the hub included: each link on it resolves, and each meets the accessibility floor — a `lang` attribute, a `<main>` landmark, a skip link. A page whose stylesheet or script link is wrong renders anyway, so nothing else will catch it. A session that wrote no page marks `n/a — no page written`
7. Append one session line to `transcript.md`, shaped per the grammar in its header comment — your only transcript access
8. **Rewrite `HANDOFF.md` last** ([HANDOFF-FORMAT.md](HANDOFF-FORMAT.md))

## Unit complete — a checkable state, not a judgment

Declared at exit when: frontier empty ∧ no fog left in the unit plan ∧ every `unit.md` outcome maps to ≥1 resolved ticket ∧ no `work/` submission awaits feedback ∧ the recall refresh is done. Declared in the transcript session line and `HANDOFF.md`'s completion block ([HANDOFF-FORMAT.md](HANDOFF-FORMAT.md)). "Complete" means *delivered as planned* — nothing more; `/audit` and `/academic-advisor` take it from there.

## Boundaries

- **Writes**: `lessons/`, `units/NN-<slug>/.assets/`, the unit's `.tickets/` and `.records/`, `work/` briefs and feedback, `look.md` (a correction appended in the user's own words), `learner.md` (curated triage only), `HANDOFF.md` (full rewrite at exit), `index.html`, `transcript.md` (append session lines only).
- **Never**: judge attainment or score the recall page; choose the next unit; write the course's shared `.assets/`; edit `unit.md`, `roadmap.md`, or attainment lines; read `.audit/`, the transcript body, or `playground/` uninvited.
