Metadata-Version: 2.4
Name: eduvis
Version: 0.3.0
Summary: An open, curriculum-aware schema for educational content
Author-email: seehiong <seehiong@gmail.com>
License: Apache-2.0
Project-URL: Homepage, https://github.com/seehiong/eduvis
Project-URL: Repository, https://github.com/seehiong/eduvis
Project-URL: Documentation, https://seehiong.github.io/eduvis/showcase/
Project-URL: Issues, https://github.com/seehiong/eduvis/issues
Keywords: education,schema,pedagogy,lesson,curriculum,yaml
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Education
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.3.0; extra == "dev"
Requires-Dist: pylint>=3.0.0; extra == "dev"
Dynamic: license-file

# EduVis Schema

**An open, curriculum-aware schema for educational content.**

EduVis describes the **educational meaning** of learning experiences — what elements are, what they do, how they relate, where they belong, and how the lesson flows. Renderers translate that meaning into SVG, Canvas, React, Flutter, PDF, or animated video.

Inspired by the philosophy behind Markdown, Mermaid, and Model Context Protocol (MCP):

> Separate meaning from rendering.

---

## Getting Started

**Requirements:** Python 3.10+

### Option 1: Install from PyPI (Recommended for general use)

```bash
pip install eduvis
```

### Option 2: Clone and run locally with uv (Recommended for development)

```bash
git clone https://github.com/seehiong/eduvis
cd eduvis
uv sync
```

Then prefix commands with `uv run` (or use the globally installed `eduvis` if installed via PyPI/pip):

```bash
# Validate showcase lessons
uv run eduvis validate docs/showcase/lesson-negative-numbers.yaml
uv run eduvis validate docs/showcase/lesson-geometry-triangles.yaml
uv run eduvis validate docs/showcase/demo-adaptive-remediation.yaml

# Render showcase lessons to SVGs
uv run eduvis render docs/showcase/lesson-negative-numbers.yaml -o output/negatives/
uv run eduvis render docs/showcase/lesson-geometry-triangles.yaml -o output/geometry/
uv run eduvis render docs/showcase/demo-adaptive-remediation.yaml -o output/remediation/

# Utility commands
uv run eduvis docs --subjects math
uv run eduvis schema -o schemas/
```


### Option 3: Install locally with pip

```bash
git clone https://github.com/seehiong/eduvis
cd eduvis
pip install -e .
```

### Run the Tests

```bash
uv sync --extra dev
uv run pytest tests/ -v
```

### Code Quality and Maintainability Checks

To keep the codebase maintainable and clean, we enforce code quality and maintainability limits locally. These checks monitor:

1. **Cyclomatic Complexity**: Functions must have a McCabe complexity $\le 10$.
2. **Function Length**: Functions are restricted to a maximum of 50 statements.
3. **Nesting Depth**: Block nesting depth is restricted to at most 3 levels.
4. **Duplication Detection**: Code replication/duplication of 4 or more lines is flagged.
5. **Module Size**: Python files (modules) are limited to a maximum of 1000 lines.

To run these checks, ensure your development dependencies are synced:

```bash
uv sync --extra dev
```

Then run all quality checks with a single command:

```bash
uv run python scripts/run_checks.py
```

Alternatively, you can run the individual tools manually:

```bash
# Run Ruff for style, complexity, and function length
uv run ruff check eduvis tests scripts

# Run Pylint for nesting depth, module size, and duplication
uv run pylint eduvis tests scripts
```


To see every registered element type rendered to SVG in one pass:

```bash
uv run eduvis render docs/examples/renderer_test.yaml -o output/renderer_test/
```

This produces one SVG per element type (`test_number_line.svg`, `test_text_list.svg`, `test_math_grid.svg`, `test_solid_cube.svg`, … `test_solid_cylinder.svg`) — useful for checking renderer output after code changes.

---

## What EduVis Is

EduVis is **not** an SVG schema.

EduVis is a machine-readable instructional model.

It captures the structure of good tutoring — the same structure behind effective human instructors: no skipped steps, visual intuition before abstraction, confidence-building before challenge, and retrieval to lock it in long-term.

EduVis is to educational experiences what Markdown is to documents and Mermaid is to diagrams.

A specification can be rendered as SVG, PDF, slides, interactive lessons, or animated videos while preserving pedagogical intent.

---

## The Problem

Most diagram libraries describe visuals. EduVis describes **learning experiences**.

A number line in a textbook, a number line used to discover a rule, and a number line shown during a recall exercise are pedagogically different objects. They happen to look the same. Today's tools treat them identically.

```yaml
# What every library gives you
type: number_line
range: [-10, 10]
highlight: [-3, 5]
```

EduVis preserves the meaning that gets lost the moment most tools export to SVG:

```yaml
type: number_line
placement:
  lesson_phase: explore
  memory_role: anchor
  difficulty: starter
actions:
  - compare: [-3, 5]
range: [-10, 10]
```

But more importantly, EduVis describes where this element sits inside a proven teaching pattern — something no diagram library models at all.

---

## Specification Status & Tooling

This is not a theoretical schema. The placement model, element types, and LLM prompt vocabulary have been validated in real educational pipelines and are designed for production use.

* **[Interactive Showcase](docs/showcase/)**: View complete, production-grade lessons rendered to SVG.
* **[Live Schema Editor](docs/showcase/editor.html)**: Write and preview your own EduVis YAML specifications in real-time. It runs the full Python rendering library entirely client-side in the browser using WebAssembly (Pyodide).

---

## Two-Layer Architecture

EduVis is deliberately split into two companion specifications.

```
EduVis-Core
  ↓
EduVis-Presentation
```

### EduVis-Core

The educational meaning layer. Renderer-agnostic, stable, and the rare part.

Covers five concerns:

| Concern | What it answers |
|---|---|
| **Elements** | What content type is this? |
| **Actions** | What does this element ask the student to do? |
| **Relationships** | How does this element relate to others in the lesson? |
| **Placement** | Where does it live in the lesson and in memory? |
| **Progression** | What is the instructional flow of the whole lesson? |

### EduVis-Presentation *(companion spec, future)*

The animation and timing layer. Renderer-specific, layered on top of Core.

Covers: zoom, pan, pause, reveal sequencing, highlight animation, narration timing.

**Why the split matters:** mixing these too early produces a video animation engine, not an educational standard. The educational semantics are the rare and valuable part. Animation is comparatively easy to layer on later.

A Core spec can be rendered to a static PDF today and to a YouTube-style animated lesson tomorrow — without changing a single field.

---

## EduVis-Core

### Elements

The content types. Educational primitives, not drawing primitives.

```yaml
type: number_line
range: [-10, 10]
highlight:
  - value: -3
    label: "-3°C"
    color: blue
  - value: 3
    label: "3°C"
    color: red
direction_labels:
  left: Colder
  right: Warmer
```

`number_line`, `fact_boxes`, `multiple_choice`, `hint_list` — these are pedagogical roles, not visual shapes. See [Element Reference](#element-reference) for the full vocabulary.

---

### Actions

What the element asks the student to do — the educational intent of the interaction.

```yaml
actions:
  conceptual:
    - compare: [-3, 5]          # notice a difference between two values
    - predict: unknown          # student fills in a missing value
    - identify: misconception   # student spots the error before it is revealed
    - retrieve: rule            # student recalls without looking back
    - apply: signed-number-ordering  # student applies a rule to a new case
  procedural:
    - substitute: { from: x, to: 3 }   # step-by-step transformation
    - simplify                  # reduce an expression
    - calculate                 # perform arithmetic
    - round: { decimal_places: 2 }
```

Actions are split into two categories:

**Conceptual** — what the student does cognitively:

| Action | What it means |
|---|---|
| `compare` | Draw attention to two elements in relation |
| `predict` | Student must supply a value before it is revealed |
| `identify` | Student spots the error or pattern before explanation |
| `retrieve` | Student recalls from memory without re-reading |
| `apply` | Student applies a rule to a new case |

**Procedural** — step-by-step mathematical transformations (the no-skipped-steps principle):

| Action | What it means |
|---|---|
| `substitute` | Replace a variable or expression — one explicit step |
| `simplify` | Reduce an expression — one explicit step |
| `calculate` | Perform arithmetic — one explicit step |
| `round` | Round to a specified precision — one explicit step |

Actions are **not** animation instructions. `compare` does not mean "animate an arrow between two values." It means "this element exists to make a comparison salient." The presentation layer decides how.

Procedural actions enforce `no_skipped_steps`: every transformation is named, so an AI generator cannot collapse two steps into one and a renderer can show working line by line.

---

### Relationships

How elements relate to other elements within a lesson. Enables lesson-level coherence checking and AI lesson assembly.

```yaml
relationships:
  anchors:
    - fraction_model          # this element is the concrete anchor for the concept
  contradicts:
    - misconception_example   # this element corrects the previous one
  precedes:
    - practice_question       # this element scaffolds the next element
  reinforces:
    - hook_scenario           # this element brings back the opening memory
```

| Relationship | What it means |
|---|---|
| `anchors` | This element establishes the concrete memory anchor for a concept |
| `contradicts` | This element corrects or challenges a previous element |
| `precedes` | This element scaffolds the element that follows |
| `reinforces` | This element recalls an earlier anchor to strengthen it |
| `parallels` | Two elements show the same concept at different abstraction levels |
| `remediation_for` | This element is shown when a student fails a linked element — scaffolds a retry |

**Adaptive tutoring pattern** — the `remediation_for` relationship encodes the CHECK → HINT branching loop used in intelligent tutoring systems without requiring a separate adaptive-paths pillar:

```yaml
- id: check_prime_identification
  type: multiple_choice
  placement:
    lesson_phase: independent_practice
    memory_role: practice
    difficulty: starter
  question: Which of these is a prime number?
  options: {A: "1", B: "2", C: "4", D: "6"}
  answer: "B"

- id: hint_prime_identification
  type: hint_list
  placement:
    lesson_phase: guided_practice
    memory_role: example
    purpose: worked_example
  relationships:
    remediation_for:
      - check_prime_identification
  items:
    - "List the factors of each option"
    - "A prime has exactly two factors: 1 and itself"
  final: "Choose the number with exactly two factors"
```

The runtime reads `remediation_for` and branches: show `check_prime_identification` first; if the student answers incorrectly, show `hint_prime_identification` and retry. The progression block still declares `guided_practice` before `independent_practice` — preserving pedagogical intent regardless of document order.

---

### Placement

Where the element lives in the lesson and in long-term memory. Three independent layers.

```yaml
placement:
  # Layer 1 — Layout: where on the screen
  layout_zone: center         # center | left | right | full | bottom
  visual_weight: primary      # primary | supporting

  # Layer 2 — Pedagogical: where in the lesson
  lesson_phase: explain       # hook | explore | explain | guided_practice | independent_practice | challenge | reflect | recall
  purpose: conceptual_model   # conceptual_model | worked_example | comparison | procedure | summary
  difficulty: routine         # starter | routine | challenge  (meaningful in practice phases)

  # Layer 3 — Memory: what role in retention
  memory_role: anchor         # anchor | example | practice | misconception_fix | retrieval | review
```

**Lesson phases:**

| Phase | What it means |
|---|---|
| `hook` | Concrete scenario before the concept is named |
| `explore` | Student observes a pattern before the rule is stated |
| `explain` | Rule or concept is revealed — `conceptual_model` purpose before `procedure` |
| `guided_practice` | Instructor walks through a worked example with the student following each step |
| `independent_practice` | Student applies the concept without guidance; difficulty set by `difficulty` field |
| `challenge` | Stretch problem that extends beyond routine application |
| `reflect` | Student articulates what they learned |
| `recall` | Student retrieves without re-reading — builds long-term memory |

**Difficulty levels** (used in `independent_practice` and `challenge` phases):

| Level | What it means |
|---|---|
| `starter` | Intentionally easy — builds confidence before the concept feels hard |
| `routine` | Typical exam-style problems — the core of independent practice |
| `challenge` | Harder realistic problems or stretch questions |

**Memory roles:**

| Role | What it means |
|---|---|
| `anchor` | The one element the student should remember weeks later |
| `example` | Demonstrates the concept in a specific case |
| `practice` | Used during in-lesson application |
| `misconception_fix` | Corrects a specific common error |
| `retrieval` | Shown during a recall exercise |
| `review` | Appears in a future lesson as a spaced repetition cue |

---

### Progression

The instructional flow of the whole lesson. This is the pillar that makes EduVis more than a diagram library.

Progression operates at the **lesson level**. Placement operates at the **element level**. Together they encode the teaching pattern — not just the individual elements, but the sequence that makes learning stick.

```yaml
progression:
  pattern: confidence_ladder      # the named teaching pattern
  pedagogy:
    confidence_first: true        # begin with starter problems before routine ones
    explain_why: true             # conceptual_model purpose before procedure
    no_skipped_steps: true        # every transformation is an explicit action
  phases:
    - phase: hook
    - phase: explore
    - phase: explain
      purpose: conceptual_model
    - phase: explain
      purpose: procedure
    - phase: guided_practice
      count: 1
    - phase: independent_practice
      difficulty: starter
      count: 3
    - phase: independent_practice
      difficulty: routine
      count: 5
    - phase: challenge
      count: 1
    - phase: recall
      count: 2
```

**Named patterns:**

| Pattern | What it means |
|---|---|
| `confidence_ladder` | Hook → Explore → Explain → Guided → Starter Practice → Routine Practice → Challenge → Recall. No steps skipped, confidence built before complexity introduced. |
| `direct_instruction` | Hook → Explain → Guided → Independent Practice → Recall. Shorter sequence for procedural topics where exploration is less useful. |
| `flipped_recall` | Recall → Hook → Explore → Explain → Practice. Opens with retrieval to activate prior knowledge before new content. |

**Pedagogy flags:**

| Flag | What it means |
|---|---|
| `confidence_first` | `starter` difficulty problems appear before `routine` ones |
| `explain_why` | A `conceptual_model` element precedes the `procedure` element |
| `no_skipped_steps` | Every mathematical transformation is an explicit action |

---

## Example

A single element from the Negative Numbers lesson — `explore` phase, number line, showing two temperatures for comparison:

```yaml
- id: explore_number_line
  type: number_line
  concepts:
    - negative_numbers
  placement:
    lesson_phase: explore
    memory_role: anchor
    difficulty: starter
  actions:
    conceptual:
      - compare: [-12, 32]
  relationships:
    anchors:
      - hook_temperature
  range: [-15, 35]
  highlight:
    - value: -12
      label: "Antarctica"
      color: blue
    - value: 32
      label: "Singapore"
      color: red
```

This element sits inside a `confidence_ladder` lesson that progresses through hook → explore → explain → guided practice → starter problems → routine problems → challenge → recall.

See [docs/showcase/lesson-negative-numbers.yaml](docs/showcase/lesson-negative-numbers.yaml) for the full lesson spec.

---

## Why the Five Pillars Matter

The insight from studying effective human tutors: the diagrams are about 20% of the value. The other 80% is the sequence.

Without EduVis, an AI lesson generator asks:

> *Draw three diagrams about negative numbers.*

With EduVis, it asks:

> *I need one `anchor` element in the `explore` phase, a `conceptual_model` before the `procedure` in the `explain` phase, one `guided_practice` worked example, three `starter` practice problems to build confidence, five `routine` problems, one `challenge`, and two `retrieval` items — following `confidence_ladder` with `explain_why` and `no_skipped_steps`.*

The generator is no longer assembling graphics. It is assembling a **learning experience** — one that follows the same structure that makes great human tutors effective.

The instructional patterns that live inside the heads of great tutors become explicit, machine-readable, and consistently reproducible. That is the gap no SVG library, diagram tool, or LLM prompt currently fills.

---

## Using with LLMs

EduVis exposes its full five-pillar vocabulary as a runtime-generated system prompt block — the same pattern MCP uses to announce tool schemas to a model.

Inject it before asking an LLM to write lesson specs:

```python
from eduvis.core import format_prompt_docs

system_prompt = f"""
You are an instructional designer writing EduVis lesson specs.
Follow the schema exactly — only use elements, phases, and actions listed below.

{format_prompt_docs(["math"])}
"""
```

Or generate it from the CLI:

```bash
python -m eduvis docs --subjects math
python -m eduvis docs --subjects math --output vocab.txt
```

The vocabulary covers all five pillars in one block: lesson skeleton, progression patterns, placement model, actions vocabulary, relationship types, and element field schemas — everything an LLM needs to produce a valid spec without guessing at field names.

**Sample output** — the block below is generated from `python -m eduvis docs --subjects math` at the current release. It is illustrative, not exhaustive; the actual output updates automatically as elements are added.

<details>
<summary>View sample LLM vocabulary (v0.1, math)</summary>

> Full reference: [docs/llm_system_prompt.md](docs/llm_system_prompt.md)

```
## EduVis Lesson Structure

Every lesson YAML has four top-level keys: curriculum, lesson, progression, content.

curriculum:
  code: string            # curriculum code e.g. "SEC-math-2027"
  topic: string           # topic code e.g. "N1.6"

lesson:
  title: string           # human-readable lesson title
  concepts:               # optional list of target concepts
    - string

progression:
  pattern: confidence_ladder | direct_instruction | flipped_recall
  pedagogy:
    confidence_first: true | false
    explain_why: true | false
    no_skipped_steps: true | false
  phases:
    - phase: <lesson_phase>
      purpose: <purpose>       # optional, use in explain phase
      difficulty: <difficulty> # optional, use in practice phases
      count: <integer>         # optional, number of elements in this phase

content:
  - id: string             # unique identifier within the lesson
    type: <element_type>   # see Element Types below
    concepts:              # optional list of concepts taught by this element
      - string
    placement:
      lesson_phase: hook | explore | explain | guided_practice |
                    independent_practice | challenge | reflect | recall
      memory_role:  anchor | example | practice | misconception_fix |
                    retrieval | review
      difficulty:   starter | routine | challenge   # optional
      purpose:      conceptual_model | procedure | worked_example |
                    comparison | summary             # optional
    actions:                                        # optional
      conceptual:
        - compare: [-3, 5]
        - predict: unknown
      procedural:
        - substitute: {from: x, to: 3}
        - simplify
    relationships:                                  # optional
      anchors:         [hook_temperature]
      precedes:        [practice_starter_1]
      remediation_for: [check_element_id]
    <element-specific fields...>

## Element types (math, v0.1)
  number_line      range, highlight, direction_labels, caption
  fraction_model   shape: circle|bar|grid, total_parts, shaded_parts
  bar_model        bars: [{label, value, color}], difference
  coordinate_plane x_range, y_range, plots: [{type, equation, color}]
  geometry_shape   vertices, labels, side_labels, angles
  solid_shape      shape: cube|cone|cylinder|pyramid, dimensions, color
  factor_array     number: N
  math_grid        rows: [[cells]], headers
  text_list        items: [strings]
  fact_boxes       items: [{text, border_color}]
  example_panel    items: [{heading, body}]
  callout_box      title, lines, border_color
  summary_list     items: [strings]
  multiple_choice  question, options: {A, B, C, D}
  hint_list        items: [strings], final: string
```

</details>

---

## 3D Geometry: Solid Shapes

The `solid_shape` element renders 3D solids using isometric projection—perfect for teaching volume, surface area, and spatial reasoning.

```yaml
type: solid_shape
shape: cylinder                    # cube, rectangular_prism, pyramid, cone, cylinder, etc.
dimensions: [3, 5]                # [width, height] for cone/cylinder; [w, h, d] for prism
color: blue
label: "Volume = πr²h"            # optional label below shape
show_dimensions: true             # optional: overlay radius/height measurements on shape
```

**Supported shapes:**
- `cube` — regular cube (use single dimension: `[side]`)
- `rectangular_prism` — box with custom width, height, depth (`[w, h, d]`)
- `triangular_prism` — prism with triangular cross-section
- `pyramid` — square pyramid with apex
- `cone` — circular cone with apex (`[diameter, height]`)
- `cylinder` — circular cylinder (`[diameter, height]`)

**Features:**
- **Isometric projection** — automatic 3D perspective from 2D coordinates
- **Auto-scaling** — all shapes fit the content zone, dimensions stay proportional
- **Dimension labels** — use `show_dimensions: true` to overlay radius/height measurements (yellow text)
- **Custom labels** — `label` field renders below the shape for captions or formulas

**Cylinder improvements:**
- Darker bottom, lighter top to emphasize 3D depth
- All 16 vertical edges visible
- Bold top edge outline

See `docs/examples/renderer_test.yaml` for live examples: `test_solid_cube.svg`, `test_solid_cone.svg`, `test_solid_cylinder.svg`, etc.

---

## Python API Usage

You can easily integrate `eduvis` validation and prompt generation into your custom Python scripts and LangChain pipelines.

### Programmatic Validation
Validate lesson specs dynamically:
```python
import yaml
from eduvis.core import validate_lesson

# Load your generated lesson YAML
with open("lesson.yaml", "r") as f:
    lesson_data = yaml.safe_load(f)

# Run the five-pillar validator
warnings = validate_lesson(lesson_data)
if not warnings:
    print("Lesson is valid!")
else:
    print(f"Validation warnings: {warnings}")
```

### Programmatic LLM Vocabulary (LangChain Integration)
Retrieve the vocabulary string to inject directly into your LangChain prompt templates:
```python
from langchain_core.prompts import ChatPromptTemplate
from eduvis.core import format_prompt_docs

# Generate curriculum-specific vocab docs (e.g., for Mathematics)
eduvis_vocab = format_prompt_docs(["math"])

# Inject into LangChain Prompt Templates
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are an instructional designer. Use the following EduVis schema rules:\n\n{vocab}"),
    ("human", "Generate a lesson spec for: {topic}")
])

chain = prompt | llm
# result = chain.invoke({"vocab": eduvis_vocab, "topic": "adding fractions"})
```

---

## Element Reference

**Current focus: Mathematics.**

Science and Humanities element types and renderers are planned for a future release.

> [docs/examples/renderer_test.yaml](docs/examples/renderer_test.yaml) contains one working slide per element type. Run it with `eduvis render` to get a visual catalog of every renderer.

### Generic — all subjects

| Element | Synopsis |
|---|---|
| `text_list` | `items: [strings]` |
| `fact_boxes` | `items: [{text, color}]` |
| `example_panel` | `items: [{heading, body}]` |
| `callout_box` | `title, lines, color` |
| `summary_list` | `items: [strings]` — use on closing elements |
| `multiple_choice` | `question, options: {A, B, C, D}` |
| `hint_list` | `items: [strings], final: string` |
| `number_line` | `range, highlight, direction_labels, caption` |

### Mathematics

| Element | Synopsis |
|---|---|
| `fraction_model` | `shape: circle\|bar\|grid, total_parts, shaded_parts` |
| `bar_model` | `bars: [{label, value, color}], difference` |
| `coordinate_plane` | `x_range, y_range, plots: [{type, equation, color}]` |
| `geometry_shape` | `vertices, labels, side_labels, angles` |
| `factor_array` | `number: N` — dot grid for factors and primes |
| `math_grid` | `rows: [[cells]], headers` — column arithmetic |

---

## EduVis-Presentation (v0.3)

The presentation layer is a companion specification that sits on top of EduVis-Core. It controls the animation, reveal sequencing, and interactive player behavior without modifying the underlying pedagogical meaning.

```yaml
presentation:
  slides:
    - id: explore_number_line
      advance: manual
      duration: 5.0
      reveals:
        - target: explore_number_line
          steps:
            - index: 0
              visible_items: [0]
              caption: "Let's compare these two temperatures."
            - index: 1
              visible_items: [0, 1]
              highlight: 
                target: "value_-12"
                style: "pulse"
              viewport:
                zoom: 1.5
                center: [-12, 0]
```

**Key Features:**
- **Slides**: Maps to existing Core element IDs.
- **Reveals**: Step-by-step unhiding of element internals (e.g., list items, math grid rows).
- **Viewport**: Declarative zoom and pan commands.
- **Highlights**: Animate specific targets to draw attention.
- **Audio/Timing**: `audio_file`, `audio_offset`, and `auto_advance_after` for narration syncing.

### IDE Schema Validation
To enable autocomplete, tooltips, and real-time schema validation in IDEs (like VS Code with the YAML extension), reference the schema at the top of your files:

For lesson YAML files:
```yaml
# yaml-language-server: $schema=https://eduvis.dev/schemas/lesson.schema.json
curriculum:
  code: s1_sec_math
```

For sidecar `presentation.yaml` files:
```yaml
# yaml-language-server: $schema=https://eduvis.dev/schemas/presentation.schema.json
slides:
  - id: slide_01
    advance: manual
```

---

## Roadmap

### v0.1 — Core Schema and SVG Renderer
- Formal JSON Schema for all element types
- Placement model: all three layers, including `difficulty`
- Actions vocabulary: initial set including step-by-step transformation actions
- Progression model: named patterns and pedagogy flags
- Built-in SVG reference renderer
- Secondary Mathematics examples

### v0.2 — Curriculum Knowledge Model
- Relationships between elements within a lesson
- Curriculum metadata block (`code`, `topic`)
- Lesson-level pedagogical validation (chronological sequence, progression coverage, concepts coherence, anchor density limits)
- Learning outcomes mapping
- Prerequisite and remediation relationships
- Assessment objectives
- Curriculum graph validation

### v0.3 — EduVis-Presentation (Current)
- Interactive presentation mode (v0.3.0 player)
- Companion `presentation` schema layered cleanly over Core
- Reveal sequencing, highlight/zoom annotations, and viewport commands
- Narration timing hooks

### v0.4 — Assessment and Validation Engine (Upcoming)
- Canonical action validation model
- Step-by-step solution representation
- Rule-based answer checking (client-side, no LLM inference)
- Symbolic equivalence checking
- Misconception detection rules
- Assessment event schema
- Mastery model and Assessment objective mapping

### v0.5 — Adaptive Learning and Remediation
- Multi-path solution support
- Remediation relationships
- Hint generation from failed actions
- Branch-on-fail assessment flows
- Confidence tracking and Mastery evidence graph
- Learning pathway recommendations operating on the curriculum graph

### v0.6 — Curriculum Graph and Knowledge Engine
- Cross-lesson prerequisite graph
- Concept dependency graph
- Outcome coverage analysis
- Curriculum completeness validation
- Curriculum traversal APIs

### v0.7 — AI Generation and Tutoring
- Structured lesson, assessment, and visual generation
- Tutoring workflows

### v1.0 — Autonomous Curriculum Factory
- Agent-based curriculum generation
- Curriculum review workflows
- Standards mapping and multi-framework support
- Curriculum QA and Syllabus generation

---

### Governance and Quality (Parallel Track)
- Schema RFC process
- Architectural fitness tests
- Schema validation suites
- Contributor guidelines
- Reference curriculum implementations
- Continuous schema evolution (v0.1–v1.0)

---

## Project Structure

```text
eduvis/ (repository root)
├── pyproject.toml            ← package metadata and dependencies
├── uv.lock                   ← pinned dependency versions
├── LICENSE                   ← Apache 2.0 License
├── README.md                 ← this documentation file
├── .gitignore                ← untracked files to ignore
│
├── eduvis/                   ← Python package source code
│   ├── __init__.py           ← package entrypoint & exported APIs
│   ├── __main__.py           ← entrypoint for running directly as a script
│   ├── cli.py                ← Click CLI commands implementation
│   │
│   ├── core/                 ← EduVis-Core: schema, validation, prompt vocabulary
│   │   ├── registry.py       ← ElementRegistry (specifications list + prompt docs)
│   │   ├── validator.py      ← five-pillar lesson validator
│   │   ├── prompt.py         ← format_prompt_docs() for LLM prompts
│   │   ├── elements/
│   │   │   ├── generic.py    ← generic element field definitions
│   │   │   └── math.py       ← mathematics element field definitions
│   │   └── schemas/
│   │       ├── placement.py  ← schema definitions for placement (phases, roles)
│   │       ├── actions.py    ← schema definitions for actions
│   │       ├── relationships.py ← schema definitions for relationships
│   │       └── progression.py ← schema definitions for progression patterns
│   │
│   ├── renderers/
│   │   └── svg/              ← Python reference renderer (SVG output)
│   │       ├── spec_renderer.py  ← SVGSpecRenderer — YAML spec to SVG
│   │       ├── primitives.py     ← canvas constants and drawing helpers
│   │       ├── renderers_base.py ← generic element renderers
│   │       └── renderers_math/   ← mathematics element renderers
│   │
│   └── schemas/              ← pre-generated JSON Schema files packaged with the library
│       ├── placement.schema.json
│       ├── actions.schema.json
│       ├── relationships.schema.json
│       ├── progression.schema.json
│       └── lesson.schema.json
│
├── docs/                     ← Documentation and showcase files
│   ├── llm_system_prompt.md  ← generated vocabulary reference for LLMs
│   ├── examples/
│   │   ├── mixed_card_demo.yaml   ← mixed card layout demo (decimal subtraction)
│   │   └── renderer_test.yaml     ← one slide per element type (visual catalog)
│   └── showcase/
│       ├── lesson-negative-numbers.yaml   ← canonical negative numbers spec
│       ├── lesson-geometry-triangles.yaml ← geometry shape triangles lesson spec
│       └── demo-adaptive-remediation.yaml ← adaptive remediation flow spec

│
├── schemas/                  ← pre-generated JSON Schema files at the repository root
│   ├── placement.schema.json
│   ├── actions.schema.json
│   ├── relationships.schema.json
│   ├── progression.schema.json
│   └── lesson.schema.json
│
└── tests/                    ← Test suite
    ├── test_validate.py      ← validator smoke tests
    └── test_schema_export.py ← JSON Schema export smoke tests
```


---

## Long-Term Vision

```text
Learning Intent
       ↓
EduVis-Core  (educational meaning — stable, renderer-agnostic)
  Elements · Actions · Relationships · Placement · Progression
       ↓
EduVis-Presentation  (timing, animation — renderer-specific, layered on top)
       ↓
Any target: SVG · React · Flutter · PDF · YouTube · Interactive platform
```

Just as Markdown became the standard for text, EduVis aims to become the standard for educational content — where **progression, placement, and actions are as important as the element itself**.

---

## Status

Early design. Reference implementation live in Nova Tutor (Singapore Secondary Mathematics).

Contributions and feedback welcome.

---

## License

This project is licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.
