Skill: trondw/math-worksheets (version 2.0.0)

--- name: math-worksheets description: Generate professional math practice worksheets and full answer keys as PDFs. Compiles LaTeX to PDF using tectonic (free, no account needed). Supports any math topic from elementary through high school (Pre-Algebra, Algebra 1/2, Geometry, Pre-Calc). Handles coordinate plane grids, geometric figures, tables, and multi-part problems. Use when a user asks for a math worksheet, practice problems, homework help sheet, or answer key for any K-12 math topic. --- # Math Worksheet Generator Generate a student worksheet PDF + full step-by-step answer key PDF for any K-12 math topic. Compiles LaTeX with `tectonic` (no TeX installation required — it auto-downloads packages). ## Model Selection (Automatic) This skill auto-detects the best available reasoning model and uses it for problem generation. Reasoning models (o1, o3, DeepSeek R1, Gemini DeepThink) work through math step-by-step and make significantly fewer errors than standard models. Model rankings are kept fresh via a three-layer fallback: 1. **Hosted JSON** (fetched from GitHub, 7-day cache) — updated by maintainers as models ship 2. **Bundled JSON** (`references/model-rankings.json`) — updated with each skill release on ClawhHub 3. **Hardcoded defaults** in the script — last-resort, never stale enough to cause failures To update rankings without waiting for a skill release: edit the hosted JSON at the GitHub URL in `references/model-rankings.md`. The skill picks it up within 7 days. **Step 0 — run model detection before anything else:** ```bash SKILL_DIR="$(dirname "$0")" result=$(bash "$SKILL_DIR/scripts/check_reasoning_model.sh") status=$(echo "$result" | awk '{print $1}') # FOUND, FALLBACK, or NONE model_alias=$(echo "$result" | awk '{print $2}') model_full=$(echo "$result" | awk '{print $3}') ``` Then branch on the status: **`FOUND_REASONING`** (o3, o1, DeepThink, DeepSeek R1) — best case, use for problem generation: ``` sessions_spawn(task="<problem generation prompt>", model=model_alias) ``` No warning needed. Sub-agent writes the .tex files + verify script, announces completion. **`FOUND_STRONG`** (Claude Opus) — excellent quality, use it without alarming the user: ``` sessions_spawn(task="<generation prompt>", model=model_alias) ``` Optionally add a quiet note: *"Using Opus — solid math accuracy and excellent LaTeX. For the hardest Algebra 2 problems, a reasoning model (DeepThink/o1) would be marginally better."* **`NONE`** — standard model only; proceed but surface a clear recommendation: ``` ⚠️ No reasoning model or Opus detected. Worksheet generated with [current model]. For best accuracy, especially on multi-step problems, configure one of: • Gemini 2.5 Pro DeepThink — google.generativeai.com (free tier available) • o1 / o3 — platform.openai.com • DeepSeek R1 — platform.deepseek.com (very affordable) • Claude Opus — console.anthropic.com SymPy verification will catch most errors regardless. ``` | Status | Model examples | Action | |---|---|---| | `FOUND_REASONING` | DeepThink, o1, o3, R1 | Spawn silently, no warning | | `FOUND_STRONG` | Claude Opus 4.x | Spawn silently, optional quiet note | | `NONE` | Sonnet, Flash, GPT-4o | Use current model + show recommendation | ## Prerequisites ```bash brew install tectonic # macOS/Linux — downloads packages on demand ``` Output directory (create if needed): `~/Documents/Worksheets/` ## Workflow ### 1. Gather requirements Ask (or infer from context): - **Student**: name, grade, course (e.g. "8th grade, Pre-Algebra") - **Topic**: e.g. "factoring trinomials", "solving two-step equations" - **Problem count**: default 10 if not specified - **Format preference**: timed quiz, homework practice, mixed difficulty, or topic drill **Photo input shortcut**: If the user sends a photo of homework or a textbook page, use the `image` tool to extract problem types, format, and difficulty — then mirror that style exactly. ### 2. Design problems Design problems appropriate to the student's level. Increase difficulty gradually across the set. Every problem must be mathematically correct — verify your own solutions. See `references/problem-library.md` for topic-specific problem type menus. ### 3. Write LaTeX source Write **three** `.tex` files to `/tmp/`: - `ws_TOPIC_DATE.tex` — student worksheet (blank work areas) - `ak_TOPIC_DATE.tex` — answer key (full step-by-step solutions) - `ss_TOPIC_DATE.tex` — skills summary / study guide (cheat sheet) The **skills summary** is a 1–2 page reference card the student can use while working through the worksheet or when studying. It contains: - One section per distinct skill tested (2–5 sections typical) - A **formula/rule box** (blue) per skill — the key facts and formulas - A **mini worked example** (green) per skill — brief pattern demonstration, simpler than worksheet problems - An optional **watch-out box** (orange) — common mistakes worth flagging - Optional **key vocabulary** section at the bottom See `references/latex-templates.md` → "Skills Summary / Study Guide Template" for the full shell and box macros. See `references/latex-templates.md` for document templates, coordinate planes, tables, geometric figures, and answer key patterns. **Required packages** (include in every document): ```latex \usepackage[margin=1in, top=0.75in, bottom=0.75in]{geometry} \usepackage{amsmath, amssymb} \usepackage{tikz, pgfplots} \usepackage{enumitem, fancyhdr, multicol, array, booktabs} \pgfplotsset{compat=1.18} ``` **Work space defaults**: `\vspace{5cm}` per problem; `8cm` for multi-step; `10cm+` for graphs. ### 4. Write and run the verification file Before compiling, write `/tmp/verify_TOPIC_DATE.json` — a structured data file describing each problem and its expected answer. The bundled `scripts/verify.py` evaluates this using SymPy. No generated code is ever executed. ```bash bash "$SKILL_DIR/scripts/run_verify.sh" /tmp/verify_TOPIC_DATE.json ``` **JSON format:** ```json { "topic": "graphing polynomials", "problems": [ {"id": 1, "type": "solve", "expr": "x**2 - 5*x + 6", "expected": [2, 3]}, {"id": 2, "type": "factor", "expr": "x**2 - 7*x + 12", "expected": "(x-3)*(x-4)"}, {"id": 3, "type": "eval", "expr": "(x-1)*(x+2)", "at": {"x": 0}, "expected": -2}, {"id": 4, "type": "zeros", "expr": "x*(x-3)**2", "expected": [0, 3]}, {"id": 5, "type": "expand", "expr": "(x+2)**2", "expected": "x**2 + 4*x + 4"}, {"id": 6, "type": "manual", "desc": "Graph sketch — verify visually"} ] } ``` **Type reference:** | Type | Verifiable? | What it checks | |---|---|---| | `solve` | ✅ | Roots of expr=0 match expected list | | `factor` | ✅ | Factored form matches expected | | `expand` | ✅ | Expanded form matches expected | | `eval` | ✅ | expr evaluated at given values matches expected | | `zeros` | ✅ | Zeros of expr match expected list | | `manual` | 👁 | Flagged for human review — never fails automatically | Use `manual` for: graph sketches, sign charts, word problem setups, proofs. **If verification fails (exit 1):** fix the LaTeX answer key and re-run. Do not compile until the answer key is correct. ### 5. Compile ```bash SKILL_DIR="$(dirname "$0")" bash "$SKILL_DIR/scripts/compile.sh" /tmp/ws_TOPIC_DATE.tex ~/Documents/Worksheets/ bash "$SKILL_DIR/scripts/compile.sh" /tmp/ak_TOPIC_DATE.tex ~/Documents/Worksheets/ bash "$SKILL_DIR/scripts/compile.sh" /tmp/ss_TOPIC_DATE.tex ~/Documents/Worksheets/ ``` ### 5. Deliver Send all three PDFs via the same channel the request came from: - **Telegram** → `message` tool with `filePath` (copy to `~/.openclaw/media/outbound/` first) - **iMessage/SMS** → `imsg` skill - **Email** → `gog` skill (send all three as attachments) Suggested send order: skills summary first (study guide), then worksheet, then answer key. **Printing**: Do NOT print unless explicitly asked. If asked, print worksheet + skills summary (not answer key, unless requested). Use `lpr -P <printer_name>`. ## Quality Checklist Before compiling, verify each problem: - [ ] Mathematically correct (you checked the solution) - [ ] Unambiguous problem statement - [ ] Appropriate difficulty for the student's level - [ ] Sufficient work space - [ ] Diagrams/graphs/tables included where needed - [ ] Problems vary across the set (not all the same sub-type) ## File Naming ``` ws_algebra2_factoring_2026-02-22.pdf ← worksheet ak_algebra2_factoring_2026-02-22.pdf ← answer key ss_algebra2_factoring_2026-02-22.pdf ← skills summary / study guide ``` Prefix with student name when known: `leo_ws_...`, `leo_ak_...`, `leo_ss_...` ## Troubleshooting | Problem | Fix | |---|---| | `tectonic` not found | `brew install tectonic` | | Slow first compile | Downloading packages from CTAN — wait 30–60s, faster after | | LaTeX error on line N | Check paired `$...$`, matching `\begin{}/\end{}` | | pgfplots not rendering | Ensure `\pgfplotsset{compat=1.18}` is in preamble | | PDF not created | Read full tectonic output for the specific error |

path: README.md
content: # math-worksheets — OpenClaw Skill

**v2.0.0** · [Changelog](#changelog)

Generate professional math practice worksheets, answer keys, and study guides for K-12 students. Three PDFs every time: worksheet → answer key → skills summary cheat sheet.

## Features

- **Three documents per request** — worksheet, step-by-step answer key, skills summary with formula boxes and mini examples
- **LaTeX quality** — coordinate planes, geometric figures, tables, multi-part problems via tectonic (no TeX installation required)
- **SymPy verification** — answers are verified with a computer algebra system before compiling; incorrect answers are caught before reaching students
- **Auto reasoning-model detection** — automatically uses the best available model (DeepThink, o1/o3, DeepSeek R1, Claude Opus) for math generation; shows setup guidance if none configured. All detection is local — no network calls.
- **Channel mirroring** — sends back via the same channel the request came from (Telegram, iMessage, email)
- **K-12 coverage** — Pre-Algebra through Pre-Calculus (see `references/problem-library.md` for full topic menu)

## Install

```bash
openclaw skills install math-worksheets
```

Or download `math-worksheets.skill` from [ClawhHub](https://clawhub.com) and install locally.

**Prerequisites:**
```bash
brew install tectonic   # LaTeX compiler — auto-downloads packages on first use
```

**Python 3** is also required (standard on macOS). The skill uses it for model detection and answer verification.

**sympy** is required for answer verification:
```bash
pip3 install sympy
```

## Usage

Just ask naturally:

> *"Make Lucy a 20-problem worksheet on exponents and roots"*
> *"Leo needs practice on graphing polynomials — use his homework photo as a guide"*
> *"Factoring trinomials worksheet for an 8th grader, 15 problems"*

The skill handles everything: model selection, problem generation, SymPy verification, compile, and delivery.

## Skill Contents

```
math-worksheets/
├── SKILL.md                          ← workflow and instructions
├── scripts/
│   ├── check_reasoning_model.sh     ← auto-detects best available model (local only)
│   ├── compile.sh                   ← tectonic PDF compiler wrapper
│   ├── run_verify.sh                ← gates compilation on SymPy pass
│   └── verify.py                   ← SymPy verification template
└── references/
    ├── latex-templates.md           ← LaTeX patterns (coordinate planes, figures, answer key)
    ├── problem-library.md           ← K-12 problem type menu by course
    ├── model-rankings.md            ← human-readable model guidance
    └── model-rankings.json          ← bundled model ranking reference
```

## Changelog

### v2.0.0 — 2026-02-23
- **Security:** Eliminated RCE surface — verification no longer generates or executes AI-written Python code. The AI now writes a structured JSON data file (`verify_TOPIC_DATE.json`); the fixed, auditable `scripts/verify.py` evaluates it using SymPy. No user input is ever executed as code.
- **Security:** Removed `fetch_model_config.sh` — skill no longer makes any network requests at runtime
- **Security:** Removed auto-`pip install` from `run_verify.sh`; sympy must be installed as a prerequisite (`pip3 install sympy`)
- **Security:** `check_reasoning_model.sh` is now fully local; reads OpenClaw config optionally with graceful fallback to bundled defaults
- `references/model-rankings.json` remains bundled as a static reference

### v1.0.0 — 2026-02-22
- Initial release
- Three documents per request: worksheet, answer key, skills summary
- SymPy verification gate (exit 0/1/2)
- Auto reasoning-model detection
- LaTeX compilation via tectonic
- Channel-matched delivery (Telegram, iMessage)

## License

MIT


path: references/latex-templates.md
content: # LaTeX Templates Reference

## Document Shell

```latex
\documentclass[12pt]{article}
\usepackage[margin=1in, top=0.75in, bottom=0.75in]{geometry}
\usepackage{amsmath, amssymb, tikz, pgfplots, enumitem, fancyhdr, multicol, array, booktabs}
\pgfplotsset{compat=1.18}

\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{\textbf{TOPIC Practice}}
\fancyhead[R]{\small Name: \underline{\hspace{4.5cm}}~Date: \underline{\hspace{1.8cm}}}
\fancyfoot[C]{\thepage}
\renewcommand{\headrulewidth}{0.4pt}

\newcounter{prob}
\newcommand{\problem}[1]{\stepcounter{prob}\vspace{0.4cm}\noindent\textbf{\large\theprob.}\quad #1\vspace{0.3cm}}

\begin{document}
\begin{center}
  {\LARGE\textbf{TOPIC Practice Worksheet}}\\[0.3cm]
  {\large COURSE \quad $\bullet$ \quad DATE}
\end{center}
\noindent\rule{\linewidth}{0.4pt}\vspace{0.2cm}

% [problems here]

\end{document}
```

## Problem Patterns

### Simple algebraic problem
```latex
\problem{Solve for $x$: \quad $2x^2 - 5x - 3 = 0$}
\vspace{6cm}
```

### Two-column layout (shorter problems)
```latex
\begin{multicols}{2}
\begin{enumerate}[label=\textbf{\arabic*.}, itemsep=4cm]
  \item $3x + 7 = 22$
  \item $-2(x - 5) = 14$
  \item $\dfrac{x}{4} + 3 = 9$
  \item $5x - 3 = 2x + 9$
\end{enumerate}
\end{multicols}
```

### Multi-part problem
```latex
\problem{Given $f(x) = 3x^2 - 2x + 1$, find:}
\begin{enumerate}[label=(\alph*), itemsep=3cm, leftmargin=1.5cm]
  \item $f(0)$
  \item $f(-2)$
  \item $f(x+1)$ — expand and simplify
  \vspace{2cm}
\end{enumerate}
```

### Function table
```latex
\problem{Complete the table for $y = 3x - 2$.}
\vspace{0.3cm}
\begin{center}
\begin{tabular}{|>{\centering\arraybackslash}m{1.5cm}|>{\centering\arraybackslash}m{1.5cm}|}
\hline
\textbf{$x$} & \textbf{$y$} \\
\hline
$-2$ & \rule{1.2cm}{0pt} \\[0.5cm]\hline
$0$  & \\[0.5cm]\hline
$1$  & \\[0.5cm]\hline
$3$  & \\[0.5cm]\hline
\end{tabular}
\end{center}
\vspace{1cm}
```

## Coordinate Planes

### Blank grid (student fills in — algebraic range)
```latex
\begin{center}
\begin{tikzpicture}
\begin{axis}[
    axis lines=center, xmin=-6, xmax=6, ymin=-6, ymax=6,
    xtick={-6,-4,...,6}, ytick={-6,-4,...,6},
    grid=both,
    grid style={line width=0.15pt, draw=gray!30},
    major grid style={line width=0.3pt, draw=gray!50},
    tick label style={font=\small},
    xlabel={$x$}, ylabel={$y$},
    width=9cm, height=9cm, enlargelimits=false
]
\end{axis}
\end{tikzpicture}
\end{center}
```

### Blank grid (full −10 to 10, Pre-Algebra style)
```latex
\begin{axis}[
    axis lines=center, xmin=-10, xmax=10, ymin=-10, ymax=10,
    xtick={-10,-8,...,10}, ytick={-10,-8,...,10},
    minor tick num=1, grid=both,
    grid style={line width=0.12pt, draw=gray!20},
    major grid style={line width=0.3pt, draw=gray!50},
    tick label style={font=\scriptsize},
    xlabel={$x$}, ylabel={$y$}, width=9cm, height=9cm
]
\end{axis}
```

### Completed graph (answer key — plot a function)
```latex
\addplot[blue, thick, domain=-1:5, samples=100] {x^2 - 4*x + 3};
\addplot[only marks, mark=*, mark size=2.5pt, red] coordinates {(1,0)(3,0)};   % x-intercepts
\addplot[only marks, mark=diamond*, mark size=3pt, green!60!black] coordinates {(2,-1)};  % vertex
\draw[dashed, gray] (axis cs:2,-6) -- (axis cs:2,8) node[above] {$x=2$};
```

## Geometric Figures

### Right triangle
```latex
\begin{center}
\begin{tikzpicture}[scale=1.2]
  \coordinate (A) at (0,0);
  \coordinate (B) at (4,0);
  \coordinate (C) at (4,3);
  \draw[thick] (A) -- (B) -- (C) -- cycle;
  \draw (B) ++(-.25,0) -- ++(0,.25) -- ++(.25,0);  % right angle mark
  \node[below left] at (A) {$A$};
  \node[below right] at (B) {$B$};
  \node[above right] at (C) {$C$};
  \node[below] at (2,0) {$8$};
  \node[right] at (4,1.5) {$6$};
  \node[above left] at (2,1.5) {$x$};
\end{tikzpicture}
\end{center}
```

## Answer Key Patterns

### Answer key document header
```latex
\fancyhead[L]{\textbf{TOPIC — Answer Key}}
\fancyhead[R]{\textit{For instructor/parent use}}
```

### Step-by-step solution
```latex
\problem{[Repeat full problem statement]}

\textbf{Solution:}
\begin{align*}
  2x^2 - 5x - 3 &= 0 \\
  \intertext{Factor — find factors of $2(-3)=-6$ summing to $-5$: use $-6,+1$:}
  2x^2 - 6x + x - 3 &= 0 \\
  2x(x - 3) + 1(x - 3) &= 0 \\
  (2x + 1)(x - 3) &= 0 \\
  \intertext{Zero product property:}
  2x + 1 = 0 \quad &\text{or} \quad x - 3 = 0 \\
\end{align*}
\[ \boxed{x = -\tfrac{1}{2} \quad \text{or} \quad x = 3} \]

\vspace{0.3cm}\noindent\rule{\linewidth}{0.2pt}\vspace{0.3cm}
```

### Sign chart (for polynomial graphing)
```latex
\[
\underbrace{+}_{x<-2}\ \Bigl|_{-2}\ \underbrace{-}_{-2<x<0}\ \Bigl|_{0}\ \underbrace{-}_{0<x<2}\ \Bigl|_{2}\ \underbrace{+}_{x>2}
\]
```

---

## Skills Summary / Study Guide Template

This is the **third document** generated alongside every worksheet. It's a one-to-two page reference card the student can use while working or studying.

### Document shell

```latex
\documentclass[12pt]{article}
\usepackage[margin=0.85in, top=0.7in, bottom=0.7in]{geometry}
\usepackage{amsmath, amssymb, tikz, enumitem, fancyhdr, multicol, mdframed, xcolor}

% Color palette
\definecolor{skillblue}{RGB}{30,100,180}
\definecolor{skillbluebg}{RGB}{235,244,255}
\definecolor{warnorange}{RGB}{200,90,0}
\definecolor{warnbg}{RGB}{255,243,230}
\definecolor{exgreen}{RGB}{20,120,60}
\definecolor{exgreenbg}{RGB}{230,248,238}

% Formula/rule box
\newmdenv[
  backgroundcolor=skillbluebg,
  linecolor=skillblue, linewidth=1.5pt,
  innertopmargin=6pt, innerbottommargin=6pt,
  innerleftmargin=10pt, innerrightmargin=10pt,
  skipabove=6pt, skipbelow=4pt
]{formulabox}

% Mini example box
\newmdenv[
  backgroundcolor=exgreenbg,
  linecolor=exgreen, linewidth=1pt,
  innertopmargin=5pt, innerbottommargin=5pt,
  innerleftmargin=10pt, innerrightmargin=10pt,
  skipabove=4pt, skipbelow=4pt
]{examplebox}

% Watch-out box
\newmdenv[
  backgroundcolor=warnbg,
  linecolor=warnorange, linewidth=1pt,
  innertopmargin=5pt, innerbottommargin=5pt,
  innerleftmargin=10pt, innerrightmargin=10pt,
  skipabove=4pt, skipbelow=4pt
]{watchoutbox}

% Skill section heading
\newcommand{\skillheading}[1]{%
  \vspace{0.4cm}
  {\large\textbf{\textcolor{skillblue}{#1}}}
  \vspace{0.1cm}
  \hrule height 1pt
  \vspace{0.2cm}
}

\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{\textbf{Skills Summary: TOPIC}}
\fancyhead[R]{\small\textit{Study Guide \& Reference}}
\fancyfoot[C]{\thepage}
\renewcommand{\headrulewidth}{0.4pt}

\begin{document}

\begin{center}
  {\LARGE\textbf{Skills Summary}}\\[0.2cm]
  {\large\textbf{TOPIC}}\\[0.1cm]
  {\small\textit{Use this reference while completing your worksheet or when studying.}}
\end{center}
\vspace{0.1cm}
\noindent\rule{\linewidth}{1.5pt}
\vspace{0.3cm}

% =================== SKILL 1 ===================
\skillheading{Skill 1 Name — e.g. Factoring Trinomials (a = 1)}

\begin{formulabox}
\textbf{Rule / Formula:}\\[4pt]
$x^2 + bx + c = (x + p)(x + q)$ \quad where $p + q = b$ and $p \cdot q = c$
\end{formulabox}

\vspace{0.2cm}

\begin{examplebox}
\textbf{Example:} \quad Factor $x^2 - 7x + 12$\\[4pt]
Find two numbers that \textit{add to} $-7$ and \textit{multiply to} $12$: \quad $-3$ and $-4$ ✓\\[2pt]
$\Rightarrow\quad x^2 - 7x + 12 = \boldsymbol{(x-3)(x-4)}$
\end{examplebox}

\vspace{0.2cm}

\begin{watchoutbox}
\textbf{⚠ Watch out:} Signs matter! If $c > 0$, both factors have the \textit{same sign} as $b$.\par
If $c < 0$, the factors have \textit{opposite signs}.
\end{watchoutbox}

% =================== SKILL 2 ===================
\skillheading{Skill 2 Name — e.g. Quadratic Formula}

\begin{formulabox}
\textbf{Formula:}\\[4pt]
\[
  x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
\]
\textbf{Discriminant:}\quad $\Delta = b^2 - 4ac$\par
\begin{itemize}[leftmargin=1.5cm, itemsep=1pt, topsep=2pt]
  \item $\Delta > 0$: two real solutions
  \item $\Delta = 0$: one real solution (double root)
  \item $\Delta < 0$: no real solutions (complex roots)
\end{itemize}
\end{formulabox}

\vspace{0.2cm}

\begin{examplebox}
\textbf{Example:} \quad Solve $2x^2 - 3x - 5 = 0$\\[4pt]
$a = 2,\ b = -3,\ c = -5$\quad $\Delta = 9 + 40 = 49$\\[2pt]
$x = \dfrac{3 \pm 7}{4}$\quad $\Rightarrow\quad\boldsymbol{x = \tfrac{10}{4} = \tfrac{5}{2}}$ \quad or \quad $\boldsymbol{x = \tfrac{-4}{4} = -1}$
\end{examplebox}

% =================== KEY VOCABULARY ===================
\vspace{0.3cm}
\skillheading{Key Vocabulary}

\begin{multicols}{2}
\begin{description}[leftmargin=0.5cm, itemsep=2pt, font=\normalfont\bfseries]
  \item[Term 1:] Definition here
  \item[Term 2:] Definition here
  \item[Term 3:] Definition here
  \item[Term 4:] Definition here
\end{description}
\end{multicols}

\end{document}
```

### Usage guidance

- Generate **one skill section per distinct skill** tested in the worksheet (typically 2–5 sections)
- Each section should have: a formula/rule box + 1 mini example + optional watch-out
- Keep the whole document to **1–2 pages max** — it's a reference card, not a lesson
- Vocabulary section is optional — include only when there are ≥3 important terms
- The mini examples should be **shorter and simpler** than the worksheet problems, to illustrate the pattern without being distracting
- The watch-out box is optional per skill — only add if there's a genuinely common mistake worth flagging


path: references/model-rankings.json
content: {
  "last_updated": "2026-02-22",
  "source": "bundled — update via https://github.com/stellawuellner/math-worksheets-skill",
  "tiers": {
    "FOUND_REASONING": {
      "description": "Reasoning models — step-by-step internal chain-of-thought, highest math accuracy",
      "patterns": [
        { "alias": "o3",        "match": "openai/o3" },
        { "alias": "o1",        "match": "openai/o1" },
        { "alias": "deepthink", "match": "gemini-2.5-pro-deepthink" },
        { "alias": "deepthink", "match": "gemini-2.0-pro-deepthink" },
        { "alias": "deepseek",  "match": "deepseek-r1" }
      ]
    },
    "FOUND_STRONG": {
      "description": "Strong non-reasoning models — excellent math and LaTeX quality, use when no reasoning model available",
      "patterns": [
        { "alias": "opus", "match": "claude-opus-4" },
        { "alias": "opus", "match": "claude-opus-3-5" }
      ]
    }
  }
}


path: references/model-rankings.md
content: # Math Model Rankings

This file is the **bundled fallback** used when the hosted model config cannot be fetched.
The live version is maintained at:
  https://raw.githubusercontent.com/stellawuellner/math-worksheets-skill/main/references/model-rankings.json

Last updated: 2026-02-22
Update this file when the hosted JSON is also updated.

## Current Rankings (K-12 Math Generation)

### Tier 1 — Reasoning Models (FOUND_REASONING)
Step-by-step internal reasoning. Highest math accuracy. Use for problem generation + answer keys.

| Model ID pattern | Alias | Notes |
|---|---|---|
| `openai/o3` | o3 | Best overall math as of early 2026 |
| `openai/o1` | o1 | Strong reasoning, more accessible than o3 |
| `gemini-2.5-pro-deepthink` | deepthink | Google's reasoning model, excellent |
| `gemini-2.0-pro-deepthink` | deepthink | Previous generation, still solid |
| `deepseek-r1` | deepseek | Open source, competitive with o1 |
| `deepseek/deepseek-r1` | deepseek | Full model ID variant |

### Tier 2 — Strong Non-Reasoning (FOUND_STRONG)
No step-by-step reasoning, but high quality. Excellent LaTeX and pedagogical judgment.
Use when no Tier 1 is available. SymPy verification compensates for accuracy gap.

| Model ID pattern | Alias | Notes |
|---|---|---|
| `claude-opus-4` | opus | Excellent math + best LaTeX quality |
| `claude-opus-3-5` | opus | Previous generation Opus, still strong |

### Tier 3 — Standard Models (NONE → show recommendation)
Capable but not recommended for complex algebra. SymPy verification is essential.

| Model ID pattern | Notes |
|---|---|
| `claude-sonnet-4` | Good for basic problems, weaker on multi-step |
| `gemini-2.5-flash` | Fast, adequate for Pre-Algebra level |
| `openai/gpt-4o` | Decent, not specialized for math |

## How to Update

When new models ship that should be Tier 1 or Tier 2:

1. Update the hosted `models.json` at the GitHub URL above
2. Update this file (bundled fallback)
3. Bump `last_updated` in `models.json`
4. Submit a skill update to ClawhHub

Key signals a model deserves Tier 1 promotion:
- Scores >80% on MATH benchmark or AIME
- Has documented chain-of-thought / reasoning architecture
- Consistently outperforms Sonnet-class on algebra in community testing

Resources for staying current:
- https://livebench.ai — live model benchmarks
- https://arxiv.org/list/cs.LG/recent — new model papers
- https://lmsys.org/blog — LMSYS Chatbot Arena (math category)


path: references/problem-library.md
content: # Problem Type Library

Use this as a menu when designing problem sets. Pick types that target the student's current unit.

## Elementary / Pre-Algebra (Grades 5–8)

| Type | Example |
|---|---|
| Integer operations | $-8 + (-3)$, $(-4) \times 7$ |
| Order of operations | $3 + 2 \times (8 - 5)^2 \div 6$ |
| Fraction operations | $\frac{3}{4} + \frac{5}{6}$, $2\frac{1}{3} \times 1\frac{1}{2}$ |
| Decimal ↔ fraction ↔ percent | Convert 0.375 to fraction and percent |
| Ratios & unit rate | "60 miles in 1.5 hours — find mph" |
| Proportions | $\frac{x}{15} = \frac{4}{5}$ |
| Percent: find part/whole/rate | "35% of 80 is?" |
| One-step equations | $x + 7 = -3$, $\frac{x}{4} = 12$ |
| Two-step equations | $3x - 5 = 16$ |
| Inequalities | $2x + 3 > 11$, graph on number line |
| Coordinate plane plotting | Plot and label points in all 4 quadrants |
| Perimeter & area | Rectangles, triangles, composite shapes |
| Circle: circumference & area | Given radius or diameter |
| Volume | Rectangular prism, cylinder |
| Mean / median / mode / range | From a data set |
| Writing expressions from words | "5 less than twice a number" |
| Function tables | Complete $y = 2x + 1$ for $x = -2, 0, 1, 3$ |

## Algebra 1 (Grades 8–9)

| Type | Example |
|---|---|
| Slope from two points | Find slope through $(-1, 3)$ and $(4, -2)$ |
| Slope-intercept form | Write equation, graph the line |
| Standard form ↔ slope-intercept | Convert $3x - 2y = 12$ |
| Systems by substitution | Two equations, two unknowns |
| Systems by elimination | Same |
| Graphing systems | Find intersection point |
| Factoring GCF | $12x^3 - 8x^2 + 4x$ |
| Factoring trinomials ($a=1$) | $x^2 - 7x + 12$ |
| Factoring difference of squares | $x^2 - 49$ |
| Solving quadratics by factoring | $(x-3)(x+2)=0$ |
| Quadratic formula | With discriminant analysis |
| Graphing parabolas | Vertex, intercepts, axis of symmetry |
| Exponent rules | Product, quotient, power rules |
| Simplifying radicals | $\sqrt{72}$, $\sqrt{200}$ |

## Algebra 2 (Grades 9–11)

| Type | Example |
|---|---|
| All Algebra 1 types (advanced) | Higher coefficients, complex expressions |
| Factoring trinomials ($a \neq 1$) | $6x^2 + 7x - 3$ |
| Sum/difference of cubes | $8x^3 + 27$, $x^3 - 125$ |
| Completing the square | Standard → vertex form |
| Complex numbers | $i^2 = -1$; $(3+2i)(1-4i)$ |
| Polynomial long division | $(x^3-2x^2+5x-6) \div (x-2)$ |
| Synthetic division | Same, using synthetic method |
| Rational Root Theorem | Find all rational zeros |
| Graphing polynomials | Zeros, multiplicity, end behavior, sign chart |
| Function composition | $f(g(x))$, $g(f(x))$ |
| Inverse functions | Find $f^{-1}(x)$, verify |
| Exponential functions | Growth/decay, $y = ab^x$ |
| Logarithms | Convert exp ↔ log; solve $\log_2(x+3) = 4$ |
| Log properties | Product, quotient, power rules |
| Sequences | Arithmetic and geometric; find $a_n$ |
| Systems of 3 equations | Elimination method |
| Conic sections | Circles, parabolas — standard form |

## Geometry (Grades 9–10)

| Type | Example |
|---|---|
| Segment and angle bisectors | Midpoint, angle bisector theorem |
| Parallel lines & transversals | Alternate interior, corresponding angles |
| Triangle congruence | SSS, SAS, ASA, AAS, HL — write proofs |
| Triangle similarity | AA, SAS, SSS similarity |
| Pythagorean theorem | Find missing side; converse |
| Special right triangles | 30-60-90, 45-45-90 |
| Trigonometry | sin/cos/tan; find missing sides and angles |
| Area: triangles, trapezoids | Standard formulas |
| Circles | Arc length, sector area, inscribed angles |
| Coordinate geometry | Distance, midpoint, slope proofs |
| Volume & surface area | Pyramids, cones, spheres |

## Pre-Calculus (Grades 10–12)

| Type | Example |
|---|---|
| Polynomial graphing (advanced) | Turning points, behavior analysis |
| Rational functions | Asymptotes, holes, graphing |
| Trig functions | Unit circle, graphs of sin/cos/tan |
| Trig identities | Pythagorean, reciprocal, co-function |
| Trig equations | Solve $2\sin x - 1 = 0$ on $[0, 2\pi)$ |
| Inverse trig | Find $\arcsin$, $\arccos$, $\arctan$ values |
| Vectors | Component form, magnitude, dot product |
| Polar coordinates | Convert, graph |
| Sequences & series | Sigma notation, partial sums |
| Limits (intro) | Evaluate numerically and graphically |
| Binomial theorem | Expand $(x+y)^n$ |
| Matrices | Operations, inverse, solve systems |


path: scripts/check_reasoning_model.sh
content: #!/usr/bin/env bash
# check_reasoning_model.sh — Detect the best available reasoning model for math
#
# Reads the active OpenClaw model config (if present) and checks whether a
# reasoning model or strong fallback is configured. All logic is local — no
# network requests are made.
#
# Outputs one line: "<STATUS> <alias> <full-model-id>"
#   FOUND_REASONING — a dedicated reasoning model is active (o3, DeepThink, R1, etc.)
#   FOUND_STRONG    — a strong non-reasoning model is active (Opus, etc.)
#   NONE            — only standard models found; recommend switching
#
# Exit 0 = usable model found
# Exit 1 = only standard models available

set -uo pipefail

# ── Reasoning model patterns (in priority order) ──────────────────────────────
# Format: "alias|substring-to-match-in-model-id"
REASONING_PATTERNS=(
  "o3|/o3"
  "o1|/o1"
  "deepthink|deepthink"
  "deepseek|deepseek-r1"
  "deepseek|deepseek/r1"
)

# ── Strong non-reasoning models (excellent for math, not pure reasoning) ──────
STRONG_PATTERNS=(
  "opus|claude-opus-4"
  "opus|claude-opus-3"
)

# ── Try to read configured models from OpenClaw config (optional) ─────────────
# The config file is only read if it exists. Nothing fails if it doesn't.
CONFIGURED_MODELS=""
CONFIG_PATHS=(
  "${HOME}/.openclaw/config.json"
  "${HOME}/.openclaw/openclaw.json"
)

for config_path in "${CONFIG_PATHS[@]}"; do
  if [[ -f "$config_path" ]]; then
    CONFIGURED_MODELS=$(python3 -c "
import json, sys
try:
    with open('$config_path') as f:
        cfg = json.load(f)
    models = set()
    defaults = cfg.get('agents', {}).get('defaults', {})
    for key in defaults.get('models', {}).keys():
        models.add(key.lower())
    model_cfg = defaults.get('model', {})
    primary = model_cfg.get('primary', '')
    if primary:
        models.add(primary.lower())
    for m in model_cfg.get('fallbacks', []):
        if m: models.add(m.lower())
    for m in sorted(models):
        print(m)
except Exception:
    sys.exit(0)
" 2>/dev/null || true)
    break
  fi
done

# ── Match against a pattern list ──────────────────────────────────────────────
check_patterns() {
  local -n patterns=$1
  for entry in "${patterns[@]}"; do
    local alias="${entry%%|*}"
    local substr="${entry##*|}"
    local match
    match=$(echo "$CONFIGURED_MODELS" | grep -i "$substr" | head -1 || true)
    if [[ -n "$match" ]]; then
      echo "$alias $match"
      return 0
    fi
  done
  return 1
}

# ── Check Tier 1: Reasoning models ───────────────────────────────────────────
if result=$(check_patterns REASONING_PATTERNS 2>/dev/null); then
  echo "FOUND_REASONING $result"
  exit 0
fi

# ── Check Tier 2: Strong non-reasoning ───────────────────────────────────────
if result=$(check_patterns STRONG_PATTERNS 2>/dev/null); then
  echo "FOUND_STRONG $result"
  exit 0
fi

# ── Nothing useful found ──────────────────────────────────────────────────────
echo "NONE"
exit 1


path: scripts/compile.sh
content: #!/usr/bin/env bash
# compile.sh — Compile a LaTeX file to PDF using tectonic
# Usage: compile.sh <input.tex> [output-dir]
#
# Requirements: tectonic (brew install tectonic)
# Tectonic auto-downloads any missing LaTeX packages on first use.

set -euo pipefail

TEX_FILE="${1:-}"
OUT_DIR="${2:-$(dirname "$TEX_FILE")}"

if [[ -z "$TEX_FILE" ]]; then
  echo "Usage: compile.sh <input.tex> [output-dir]" >&2
  exit 1
fi

if [[ ! -f "$TEX_FILE" ]]; then
  echo "Error: File not found: $TEX_FILE" >&2
  exit 1
fi

# Locate tectonic
TECTONIC=$(command -v tectonic 2>/dev/null || echo "/opt/homebrew/bin/tectonic")
if [[ ! -x "$TECTONIC" ]]; then
  echo "Error: tectonic not found. Install with: brew install tectonic" >&2
  exit 1
fi

mkdir -p "$OUT_DIR"

echo "Compiling: $(basename "$TEX_FILE") → $OUT_DIR/"
"$TECTONIC" "$TEX_FILE" --outdir "$OUT_DIR" 2>&1 | grep -v "^note: downloading"

PDF="${OUT_DIR}/$(basename "${TEX_FILE%.tex}").pdf"
if [[ -f "$PDF" ]]; then
  echo "✅ PDF ready: $PDF"
  echo "$PDF"
else
  echo "❌ Compilation failed — check LaTeX errors above" >&2
  exit 1
fi


path: scripts/run_verify.sh
content: #!/usr/bin/env bash
# run_verify.sh — Run worksheet answer verification
# Usage: run_verify.sh <verify_TOPIC_DATE.json>
#
# Passes the JSON verification file to the bundled verify.py script.
# No code is generated or executed from user input — only structured
# data (the JSON file) is evaluated by the fixed verify.py.
#
# Requires: python3 with sympy installed
#   pip3 install sympy
#
# Exit codes:
#   0 — all automated checks passed — safe to compile
#   1 — one or more checks FAILED — fix answer key before compiling
#   2 — manual review needed — no automated failures, safe to compile

set -uo pipefail

JSON_FILE="${1:-}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VERIFY_PY="${SCRIPT_DIR}/verify.py"

if [[ -z "$JSON_FILE" ]]; then
  echo "Usage: run_verify.sh <verify_TOPIC_DATE.json>" >&2
  exit 1
fi

if [[ ! -f "$JSON_FILE" ]]; then
  echo "Error: verification file not found: $JSON_FILE" >&2
  exit 1
fi

# ── Find Python 3 ─────────────────────────────────────────────────────────────
PYTHON=""
for candidate in "/opt/homebrew/bin/python3" "/usr/local/bin/python3" "$(command -v python3 2>/dev/null || true)"; do
  if [[ -x "$candidate" ]]; then
    PYTHON="$candidate"
    break
  fi
done

if [[ -z "$PYTHON" ]]; then
  echo "Error: python3 not found. Install Python 3 to use verification." >&2
  exit 1
fi

# ── Check sympy is available ──────────────────────────────────────────────────
if ! "$PYTHON" -c "import sympy" 2>/dev/null; then
  echo "Error: sympy is not installed." >&2
  echo "Run: pip3 install sympy" >&2
  exit 1
fi

# ── Run the fixed verification script ────────────────────────────────────────
"$PYTHON" "$VERIFY_PY" "$JSON_FILE"
EXIT_CODE=$?

exit $EXIT_CODE


path: scripts/verify.py
content: #!/usr/bin/env python3
"""
verify.py — Static SymPy verification for math worksheets.

Reads a structured JSON file of problems and answers. No user-generated
code is ever executed — only the structured data is evaluated.

Input format: /tmp/verify_TOPIC_DATE.json
  {
    "topic": "graphing polynomials",
    "problems": [
      {"id": 1, "type": "solve",  "expr": "x**2 - 5*x + 6",     "expected": [2, 3]},
      {"id": 2, "type": "factor", "expr": "x**2 - 7*x + 12",    "expected": "(x - 3)*(x - 4)"},
      {"id": 3, "type": "eval",   "expr": "(x-1)*(x+2)", "at": {"x": 0}, "expected": -2},
      {"id": 4, "type": "zeros",  "expr": "x*(x-3)**2",          "expected": [0, 3]},
      {"id": 5, "type": "expand", "expr": "(x+2)**3",            "expected": "x**3 + 6*x**2 + 12*x + 8"},
      {"id": 6, "type": "manual", "desc": "Graph sketch — verify visually"}
    ]
  }

Supported types:
  solve   — solves expr=0 for x, checks roots match expected list
  factor  — factors expr, checks string form matches expected
  eval    — evaluates expr at given variable values, checks result
  zeros   — finds zeros of expr, checks they match expected list
  expand  — expands expr, checks string form matches expected
  manual  — flagged for human review, never fails automatically

Exit codes:
  0 — all automated checks passed
  1 — one or more checks FAILED (fix answer key before compiling)
  2 — no failures, but some problems need manual review
"""

import json
import sys
import os
from sympy import (
    symbols, solve, factor, expand, sympify,
    Rational, simplify, nsimplify
)

def run_verification(json_path):
    with open(json_path) as f:
        data = json.load(f)

    problems = data.get("problems", [])
    topic = data.get("topic", "unknown")

    print(f"Verifying: {topic} ({len(problems)} problems)\n")

    results = []
    for p in problems:
        pid = p.get("id", "?")
        ptype = p.get("type", "manual")

        try:
            if ptype == "manual":
                results.append((pid, "MANUAL", p.get("desc", "manual review")))

            elif ptype == "solve":
                x = symbols('x')
                expr = sympify(p["expr"])
                roots = sorted([nsimplify(r) for r in solve(expr, x)])
                expected = sorted([nsimplify(e) for e in p["expected"]])
                ok = roots == expected
                results.append((pid, "PASS" if ok else "FAIL",
                    f"solve({p['expr']}) → {roots} (expected {expected})"))

            elif ptype == "zeros":
                x = symbols('x')
                expr = sympify(p["expr"])
                roots = sorted(set([nsimplify(r) for r in solve(expr, x)]))
                expected = sorted(set([nsimplify(e) for e in p["expected"]]))
                ok = roots == expected
                results.append((pid, "PASS" if ok else "FAIL",
                    f"zeros({p['expr']}) → {roots} (expected {expected})"))

            elif ptype == "factor":
                x = symbols('x')
                expr = sympify(p["expr"])
                factored = str(factor(expr))
                expected = str(sympify(p["expected"]))
                ok = simplify(sympify(factored) - sympify(expected)) == 0
                results.append((pid, "PASS" if ok else "FAIL",
                    f"factor({p['expr']}) → {factored} (expected {p['expected']})"))

            elif ptype == "expand":
                x = symbols('x')
                expr = sympify(p["expr"])
                expanded = str(expand(expr))
                expected = str(sympify(p["expected"]))
                ok = simplify(sympify(expanded) - sympify(expected)) == 0
                results.append((pid, "PASS" if ok else "FAIL",
                    f"expand({p['expr']}) → {expanded} (expected {p['expected']})"))

            elif ptype == "eval":
                subs = {symbols(k): nsimplify(v) for k, v in p["at"].items()}
                expr = sympify(p["expr"])
                result = expr.subs(subs)
                expected = nsimplify(p["expected"])
                ok = simplify(result - expected) == 0
                results.append((pid, "PASS" if ok else "FAIL",
                    f"eval({p['expr']} at {p['at']}) → {result} (expected {expected})"))

            else:
                results.append((pid, "MANUAL", f"unknown type '{ptype}' — manual review"))

        except Exception as e:
            results.append((pid, "FAIL", f"Error evaluating problem {pid}: {e}"))

    # Print results
    for pid, status, desc in results:
        icon = {"PASS": "✅", "FAIL": "❌", "MANUAL": "👁 "}.get(status, "?")
        print(f"  {icon} [{status}] Problem {pid}: {desc}")

    failures = [r for r in results if r[1] == "FAIL"]
    manuals  = [r for r in results if r[1] == "MANUAL"]
    passes   = [r for r in results if r[1] == "PASS"]

    print(f"\n{len(passes)} passed · {len(failures)} failed · {len(manuals)} manual")

    if failures:
        print("\n❌ Fix the answer key before compiling.")
        return 1
    if manuals:
        print("\n👁  Manual review needed for some problems — safe to compile.")
        return 2
    print("\n✅ All checks passed — safe to compile.")
    return 0


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <verify_TOPIC_DATE.json>", file=sys.stderr)
        sys.exit(1)

    json_path = sys.argv[1]
    if not os.path.exists(json_path):
        print(f"Error: file not found: {json_path}", file=sys.stderr)
        sys.exit(1)

    sys.exit(run_verification(json_path))


Security scan verdicts — ClawScan: clean | static analysis:  | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)