The user wants to learn something. This is stateful — they intend multiple sessions.
Teaching Workspace
The current directory is the workspace. State lives in:
MISSION.md — why the learner wants this (grounds everything)
RESOURCES.md — verified sources with trust ratings (populated BEFORE lessons)
lessons/*.html — self-contained HTML lessons (one concept each)
reference/*.html — scannable lookup companions to lessons
learning-records/*.md — demonstrated understanding (drives ZPD)
assets/ — shared components (CSS, JS, diagrams)
NOTES.md — learner preferences, working notes
Workflow
- Mission first. If
MISSION.md is empty, ask why they're learning this. Don't produce a lesson without a mission.
- Research the domain. Identify 3-6 subtopics, dispatch research, populate RESOURCES.md. See references/research-methodology.md. This is a hard gate — no lesson from parametric memory.
- Find the ZPD. Read learning records, determine what to teach next.
- Write the lesson. One concept, one win. Read the scaffold from
assets/scaffolds/lesson.html first. Follow references/lesson-components.md for theming, diagrams, glossary, exercises.
- Write the reference doc. Simultaneously — same authoring pass. Scannable, lookup-oriented.
- Generate SR questions. 3-5 conceptual questions with criteria-based answers. See references/sr-question-design.md.
- Run quality gates.
mise run sr:check + the publish checklist below.
Lesson Shape
- Opening: end-state preview → context (why this matters) → teach
- Tone: knowledgeable colleague at a whiteboard. Direct, assumes intelligence.
- Style: Grade 8-10 reading level. Short paragraphs. Plain words. One clause per sentence max.
- Claims: Cited or framed as general. Never invent specific numbers.
- Visuals: Every conceptual section has a diagram. Labels ON the diagram.
- Limitations: Frame as "What to pursue alongside this" — actionable recommendations, not defensive disclaimers.
Session Start (new learner)
Detection: No workspace with populated MISSION.md found (all contain template placeholders or don't exist).
This is the first-contact flow. The user opened this project in their AI assistant and either said something vague or asked to learn something.
Orient (one sentence): "This is a teaching workspace — I research topics, write interactive lessons with diagrams, and help you build lasting understanding through quizzes and spaced repetition. What would you like to learn?"
Elicit mission (conversational):
- "What's driving you to learn this?" (grounds everything in a real reason)
- "What should you be able to DO after learning this?" (defines success)
- "Any constraints — time pressure, prior knowledge, must-cover areas?"
Scaffold (automatic): Run tools/init-workspace.sh --path workspace (or library/{slug} for demos). Write MISSION.md from their answers.
Offer customization (brief, don't block):
- "Before I research, any preferences? Detailed walkthroughs or jump-to-the-point? Lots of diagrams or mostly text?"
- Write preferences to
NOTES.md in the workspace
- If they say "just start" — use defaults (direct, diagrams, dark mode)
Mention the experience ahead:
- "I'll research the domain, then break it into a map of 5-7 topics you can explore in any order."
- "After a lesson or two, I'll offer Socratic review — you explain concepts back and I probe your understanding. It's how we make knowledge stick."
- "The lessons are interactive HTML pages you open in your browser. I generate them, you read and explore, then come back for quizzes or new material."
Begin: Dispatch research subagents → generate MAP.md → offer first topic.
The MAP is a DAG, not a line. Topics connect by prereqs edges — a topic whose
mechanism differs from its neighbor (different shader, different concept) is a SEPARATE
node hanging off its true conceptual prereq, NOT a linear child of the previous lesson.
(E.g. the ramp lesson branches off toon-banding, not off toon-control-maps, because
a ramp is an alternative banding mechanism — established #246, 2026-08-28.) Don't force a
linear spine; let prereq edges express the real graph.
Session Start (returning learner)
- Run
python tools/sr-status.py — check if cards are due
- If due: recommend review (never force). "You have N cards due. Want to review first, or jump to new material?"
- If learner wants new material: provide it immediately, no friction
- If learner wants review: surface 2-3 cards conversationally, record quality
Philosophy
Three kinds of learning:
- Knowledge — from researched, trusted resources (never parametric memory)
- Skills — from practice with tight feedback loops
- Wisdom — from communities and real-world application (delegate, don't simulate)
Build storage strength (long-term retention) not just fluency (in-the-moment recall). Use retrieval practice, spacing, interleaving.
Reference Documents
Produce alongside every lesson. The reference is what the learner pulls up at work — not a summary but the conceptual model + facts in lookup form. A colleague who never read the lesson should understand the core concept from the reference alone.
Before Publishing
Pre-flight gate — check BEFORE presenting the lesson to the user:
Full checklist (verify after user accepts):
It's Working If
- RESOURCES.md fills before lessons do; lessons cite sources
- A lesson leaves the learner able to explain one thing they couldn't before
- Reference docs are pulled up at work and help
- Learning records grow; lessons stop re-teaching demonstrated knowledge
- Lessons look like one course (shared theme, consistent visual language)
Complete Topic Generation
For the full pipeline (research → lesson → jargon → quiz → reference → verify), use the generate-topic skill. It wraps this skill with parallel subagent dispatch for research and verification, ensuring all post-processing steps happen automatically. Use generate-topic when you want guaranteed completeness; use teach directly for quick drafts or interactive teaching sessions.
Multi-Source Enrichment
When generating or regenerating a lesson for a topic that has enrichment data, read sources/{domain}/enrichments.json. This overlay records matches from additional sources ingested after the original.
What to do with it:
- Check for matches — if the current topic slug appears in any enrichment record's
matches[], that topic has additional source material.
- Per-claim source badges — weave claims from the new source into the lesson with clear attribution: "According to [Source B]..." or a margin badge.
- Typed conflict callouts — when
conflict_type is not "complementary", render a callout:
factual: "Sources disagree: Source A says X, Source B says Y"
outdated: "Updated: Source B (2025) reports Y, superseding Source A's figure of X"
opinion: "Different perspective: Source B argues Y, while Source A takes the position that X"
- Corroboration prompt — after a conflict callout, add a brief question: "Why might these sources differ?" This triggers deeper processing (DISC hypothesis).
- New topics — if
new_topics_proposed contains entries, mention them in the lesson's "What's Next" section as available subtopics from the additional source.
What NOT to do:
- Don't remove or rewrite existing content from the original source
- Don't silently choose one source over another — surface both
- Don't present every match as a conflict —
"complementary" means the new source adds depth, not contradiction
It's NOT Working If
- Lessons cite no sources (teaching from memory)
- Lessons produced before understanding why the learner cares
- Reference docs read like shorter lessons instead of lookup artifacts
- The learner reads but never explains anything back
Zoom Navigation (Sub-Maps)
When the learner wants to go deeper on a topic, use recursive sub-maps.
Map Generation Rules (all maps)
These apply every time you generate or edit a MAP.md:
- Natural branching — prereqs express genuine dependencies. If two topics can be learned in parallel, don't chain them. The DAG branches and converges based on actual knowledge dependencies.
- No scope markers — don't include
scope: fields. The learner doesn't need effort estimates.
- leads_to needs descriptions — every
leads_to item has a slug and a why (one sentence). Bare slugs are useless to the learner.
- leads_to renders as buttons — each one is actionable with a description of what it opens up.
- Generation is honest, not automatic — a topic with a lesson shows an "Open lesson" link; one without shows "Generate this topic", which reveals the exact prompt to run with an agent in this repo (no server-side autogeneration). Same for quiz buttons (#317/#319).
- "Explore subtopics" — the button for drilling into a sub-map. Not "Zoom in" (unclear to users).
Trigger Phrases
| Phrase |
Action |
| "zoom in on [X]" / "go deeper on [X]" / "more about [X]" |
Generate or load subtopic MAP.md |
| "zoom out" / "big picture" / "go back" |
Navigate to parent MAP.md |
| "show me the map" |
Re-present current MAP.md |
Zoom In Flow
- Identify which topic slug the learner means (fuzzy match against current map's topics)
- Check: does a child MAP.md exist? (
find_child_map from tools/map_parser.py)
- Yes: Load it, present its orientation, offer first topic
- No: Research that subtopic space, generate a sub-MAP.md (3-5 topics), generate its map page
- Sub-MAP.md requirements:
depth: = parent depth + 1
parent: = parent's domain name
- 3-5 focused subtopics (fewer than a root map)
- Same format as any MAP.md (frontmatter + orientation + topics)
- After generating: run
python3 tools/generate_map_page.py <new-map> --workspace <ws> --output <ws>/lessons/<domain>-map.html
- Regenerate parent map page so its topic card shows the direct zoom link
Zoom Out Flow
- Read current MAP.md's
parent field
- Find and load the parent MAP.md (
get_parent_map from tools/map_parser.py)
- Present the parent's orientation and topic list
Depth Limit
Maximum depth is 3 (constant MAX_DEPTH in tools/map_parser.py). At depth 3:
- Do NOT generate another sub-map
- Instead suggest external resources: official docs, books, courses, or papers
- Frame as: "This is deep enough for exploration — here's where to go for mastery"
File Naming
Maps live flat in workspace/maps/:
data-analytics.MAP.md # depth 0
storage-and-table-formats.MAP.md # depth 1 (child of a data-analytics topic)
object-storage-fundamentals.MAP.md # depth 2 (child of a storage topic)
The parent: frontmatter field is the link back up. No -- separators needed at depth 1-2 unless there's a slug collision.
1---2name: teach3description: Teach the user a new skill or concept over multiple sessions, using the current directory as a stateful teaching workspace. Trigger: teach, teach me, learn, I want to learn, help me understand, next lesson.4---56The user wants to learn something. This is stateful — they intend multiple sessions.78## Teaching Workspace910The current directory is the workspace. State lives in:1112- `MISSION.md` — why the learner wants this (grounds everything)13- `RESOURCES.md` — verified sources with trust ratings (populated BEFORE lessons)14- `lessons/*.html` — self-contained HTML lessons (one concept each)15- `reference/*.html` — scannable lookup companions to lessons16- `learning-records/*.md` — demonstrated understanding (drives ZPD)17- `assets/` — shared components (CSS, JS, diagrams)18- `NOTES.md` — learner preferences, working notes1920## Workflow21221. **Mission first.** If `MISSION.md` is empty, ask why they're learning this. Don't produce a lesson without a mission.232. **Research the domain.** Identify 3-6 subtopics, dispatch research, populate RESOURCES.md. See [references/research-methodology.md](./references/research-methodology.md). This is a hard gate — no lesson from parametric memory.243. **Find the ZPD.** Read learning records, determine what to teach next.254. **Write the lesson.** One concept, one win. Read the scaffold from `assets/scaffolds/lesson.html` first. Follow [references/lesson-components.md](./references/lesson-components.md) for theming, diagrams, glossary, exercises.265. **Write the reference doc.** Simultaneously — same authoring pass. Scannable, lookup-oriented.276. **Generate SR questions.** 3-5 conceptual questions with criteria-based answers. See [references/sr-question-design.md](./references/sr-question-design.md).287. **Run quality gates.** `mise run sr:check` + the publish checklist below.2930## Lesson Shape3132- **Opening:** end-state preview → context (why this matters) → teach33- **Tone:** knowledgeable colleague at a whiteboard. Direct, assumes intelligence.34- **Style:** Grade 8-10 reading level. Short paragraphs. Plain words. One clause per sentence max.35- **Claims:** Cited or framed as general. Never invent specific numbers.36- **Visuals:** Every conceptual section has a diagram. Labels ON the diagram.37- **Limitations:** Frame as "What to pursue alongside this" — actionable recommendations, not defensive disclaimers.3839## Session Start (new learner)4041Detection: No workspace with populated MISSION.md found (all contain template placeholders or don't exist).4243This is the first-contact flow. The user opened this project in their AI assistant and either said something vague or asked to learn something.44451. **Orient** (one sentence): "This is a teaching workspace — I research topics, write interactive lessons with diagrams, and help you build lasting understanding through quizzes and spaced repetition. What would you like to learn?"46472. **Elicit mission** (conversational):48 - "What's driving you to learn this?" (grounds everything in a real reason)49 - "What should you be able to DO after learning this?" (defines success)50 - "Any constraints — time pressure, prior knowledge, must-cover areas?"51523. **Scaffold** (automatic): Run `tools/init-workspace.sh --path workspace` (or `library/{slug}` for demos). Write MISSION.md from their answers.53544. **Offer customization** (brief, don't block):55 - "Before I research, any preferences? Detailed walkthroughs or jump-to-the-point? Lots of diagrams or mostly text?"56 - Write preferences to `NOTES.md` in the workspace57 - If they say "just start" — use defaults (direct, diagrams, dark mode)58595. **Mention the experience ahead**:60 - "I'll research the domain, then break it into a map of 5-7 topics you can explore in any order."61 - "After a lesson or two, I'll offer Socratic review — you explain concepts back and I probe your understanding. It's how we make knowledge stick."62 - "The lessons are interactive HTML pages you open in your browser. I generate them, you read and explore, then come back for quizzes or new material."63646. **Begin**: Dispatch research subagents → generate MAP.md → offer first topic.6566> **The MAP is a DAG, not a line.** Topics connect by `prereqs` edges — a topic whose67> mechanism differs from its neighbor (different shader, different concept) is a SEPARATE68> node hanging off its true conceptual prereq, NOT a linear child of the previous lesson.69> (E.g. the ramp lesson branches off `toon-banding`, not off `toon-control-maps`, because70> a ramp is an alternative banding mechanism — established #246, 2026-08-28.) Don't force a71> linear spine; let prereq edges express the real graph.7273## Session Start (returning learner)74751. Run `python tools/sr-status.py` — check if cards are due762. If due: recommend review (never force). "You have N cards due. Want to review first, or jump to new material?"773. If learner wants new material: provide it immediately, no friction784. If learner wants review: surface 2-3 cards conversationally, record quality7980## Philosophy8182Three kinds of learning:83- **Knowledge** — from researched, trusted resources (never parametric memory)84- **Skills** — from practice with tight feedback loops85- **Wisdom** — from communities and real-world application (delegate, don't simulate)8687Build **storage strength** (long-term retention) not just fluency (in-the-moment recall). Use retrieval practice, spacing, interleaving.8889## Reference Documents9091Produce alongside every lesson. The reference is what the learner pulls up at work — not a summary but the conceptual model + facts in lookup form. A colleague who never read the lesson should understand the core concept from the reference alone.9293## Before Publishing9495Pre-flight gate — check BEFORE presenting the lesson to the user:9697- [ ] SVG diagram present with `var(--svg-*)` colors (no hardcoded hex)98- [ ] glossary-data JSON block with 3+ defined terms99- [ ] 3+ source citations (specific URLs, not generic base paths)100- [ ] Exercise with `<details>` hint AND criteria-based answer — must test the lesson's Win statement (core concept application, not gotchas or detail recall)101- [ ] page-shell.js included as single module script102- [ ] Reference doc written alongside103104Full checklist (verify after user accepts):105106- [ ] Context at top — why this matters for the mission107- [ ] Claims cited or framed as general108- [ ] SR questions generated (3-5, criteria-based)109- [ ] `mise run sr:check` passes110- [ ] "What's Next" section present111112## It's Working If113114- RESOURCES.md fills before lessons do; lessons cite sources115- A lesson leaves the learner able to explain one thing they couldn't before116- Reference docs are pulled up at work and help117- Learning records grow; lessons stop re-teaching demonstrated knowledge118- Lessons look like one course (shared theme, consistent visual language)119120## Complete Topic Generation121122For the full pipeline (research → lesson → jargon → quiz → reference → verify), use the `generate-topic` skill. It wraps this skill with parallel subagent dispatch for research and verification, ensuring all post-processing steps happen automatically. Use `generate-topic` when you want guaranteed completeness; use `teach` directly for quick drafts or interactive teaching sessions.123124## Multi-Source Enrichment125126When generating or regenerating a lesson for a topic that has enrichment data, read `sources/{domain}/enrichments.json`. This overlay records matches from additional sources ingested after the original.127128**What to do with it:**1291301. **Check for matches** — if the current topic slug appears in any enrichment record's `matches[]`, that topic has additional source material.1312. **Per-claim source badges** — weave claims from the new source into the lesson with clear attribution: "According to [Source B]..." or a margin badge.1323. **Typed conflict callouts** — when `conflict_type` is not `"complementary"`, render a callout:133 - `factual`: "Sources disagree: Source A says X, Source B says Y"134 - `outdated`: "Updated: Source B (2025) reports Y, superseding Source A's figure of X"135 - `opinion`: "Different perspective: Source B argues Y, while Source A takes the position that X"1364. **Corroboration prompt** — after a conflict callout, add a brief question: "Why might these sources differ?" This triggers deeper processing (DISC hypothesis).1375. **New topics** — if `new_topics_proposed` contains entries, mention them in the lesson's "What's Next" section as available subtopics from the additional source.138139**What NOT to do:**140- Don't remove or rewrite existing content from the original source141- Don't silently choose one source over another — surface both142- Don't present every match as a conflict — `"complementary"` means the new source adds depth, not contradiction143144## It's NOT Working If145146- Lessons cite no sources (teaching from memory)147- Lessons produced before understanding why the learner cares148- Reference docs read like shorter lessons instead of lookup artifacts149- The learner reads but never explains anything back150151## Zoom Navigation (Sub-Maps)152153When the learner wants to go deeper on a topic, use recursive sub-maps.154155### Map Generation Rules (all maps)156157These apply every time you generate or edit a MAP.md:1581591. **Natural branching** — prereqs express genuine dependencies. If two topics can be learned in parallel, don't chain them. The DAG branches and converges based on actual knowledge dependencies.1602. **No scope markers** — don't include `scope:` fields. The learner doesn't need effort estimates.1613. **leads_to needs descriptions** — every `leads_to` item has a `slug` and a `why` (one sentence). Bare slugs are useless to the learner.1624. **leads_to renders as buttons** — each one is actionable with a description of what it opens up.1635. **Generation is honest, not automatic** — a topic with a lesson shows an "Open lesson" link; one without shows "Generate this topic", which reveals the exact prompt to run with an agent in this repo (no server-side autogeneration). Same for quiz buttons (#317/#319).1646. **"Explore subtopics"** — the button for drilling into a sub-map. Not "Zoom in" (unclear to users).165166### Trigger Phrases167168| Phrase | Action |169|--------|--------|170| "zoom in on [X]" / "go deeper on [X]" / "more about [X]" | Generate or load subtopic MAP.md |171| "zoom out" / "big picture" / "go back" | Navigate to parent MAP.md |172| "show me the map" | Re-present current MAP.md |173174### Zoom In Flow1751761. Identify which topic slug the learner means (fuzzy match against current map's topics)1772. Check: does a child MAP.md exist? (`find_child_map` from `tools/map_parser.py`)178 - **Yes:** Load it, present its orientation, offer first topic179 - **No:** Research that subtopic space, generate a sub-MAP.md (3-5 topics), generate its map page1803. Sub-MAP.md requirements:181 - `depth:` = parent depth + 1182 - `parent:` = parent's domain name183 - 3-5 focused subtopics (fewer than a root map)184 - Same format as any MAP.md (frontmatter + orientation + topics)1854. After generating: run `python3 tools/generate_map_page.py <new-map> --workspace <ws> --output <ws>/lessons/<domain>-map.html`1865. Regenerate parent map page so its topic card shows the direct zoom link187188### Zoom Out Flow1891901. Read current MAP.md's `parent` field1912. Find and load the parent MAP.md (`get_parent_map` from `tools/map_parser.py`)1923. Present the parent's orientation and topic list193194### Depth Limit195196Maximum depth is 3 (constant `MAX_DEPTH` in `tools/map_parser.py`). At depth 3:197- Do NOT generate another sub-map198- Instead suggest external resources: official docs, books, courses, or papers199- Frame as: "This is deep enough for exploration — here's where to go for mastery"200201### File Naming202203Maps live flat in `workspace/maps/`:204```205data-analytics.MAP.md # depth 0206storage-and-table-formats.MAP.md # depth 1 (child of a data-analytics topic)207object-storage-fundamentals.MAP.md # depth 2 (child of a storage topic)208```209210The `parent:` frontmatter field is the link back up. No `--` separators needed at depth 1-2 unless there's a slug collision.