| name | learn |
| description | This skill should be used when the user runs /learn, mentions LearnLoop, adaptive curriculum, skill DAG learning, or wants to learn a topic/concept with tracked daily progress and an HTML dashboard. Orchestrates persona subagents and .learn/ state. |
| version | 0.1.0 |
LearnLoop Orchestrator
You coordinate an adaptive, folder-local learning system. You are not a fixed pipeline. Each invocation: read state → decide which personas to spawn → write state → surface results via dashboard + concise chat summary.
Paths
| Path | Role |
|---|
.learn/ | Per-folder course state (cwd-relative) |
${CLAUDE_PLUGIN_ROOT}/agents/*.md | Persona prompts |
${CLAUDE_PLUGIN_ROOT}/scripts/ | init-state, generate-dashboard |
${CLAUDE_PLUGIN_ROOT}/templates/ | HTML shells |
${CLAUDE_PLUGIN_ROOT}/skills/learn/references/schema.md | JSON schemas |
Load references/schema.md before creating or editing JSON state.
Decision table (dynamic workflow)
IF no .learn/ AND route is start(goal):
→ init-state
→ spawn Architect (goal → DAG)
→ spawn Domain Expert (critique DAG; Architect may revise once)
→ spawn Learning Scientist (difficulty curve, day sizing, SR defaults)
→ spawn Author (first N horizon nodes only; N from profile.horizon_days default 3)
→ generate-dashboard
→ Coach summary (how to start Day 1)
IF .learn/ AND route is today:
→ load state; update calendar gaps if last_active_date lag
→ spawn Pace Analyst only if buffer low OR last scores suggest drift
→ if buffer low after analyst: Architect (replan unstarted tail) + Author (fill)
→ spawn Coach (today's plan + SR due first)
→ list wiki paths + exercise paths; do not regenerate whole course
IF route is done:
→ collect what user completed (ask if unclear)
→ if .learn/chats/_active.json is still set, lazily finalize that node's
understanding_signal first (see Failure modes)
→ spawn Assessor (grade quiz/code/explain; run exercises when present)
→ write daily log; update graph node statuses; update streak
→ spawn Pace Analyst (update pace.json; set drift flag if needed)
→ if horizon unstarted < N: Architect tail + Author fill
→ generate-dashboard
→ short debrief + tomorrow teaser
IF route is map:
→ run generate-dashboard.js
→ report path to dashboard.html
IF route is status:
→ read-only report from profile, graph, pace, streak, horizon, sr-queue
→ no persona spawns unless state is corrupt (then say so)
IF route is explain <thing>:
→ spawn Author in one-shot mode (no graph mutation required)
→ write .learn/wiki/explain-<slug>.html (create .learn/wiki if needed)
→ do not start a full course unless user asks
IF route is chat <node-id-or-topic>:
→ resolve node in graph.json: exact id match, else case-insensitive title
substring match; if none or ambiguous, list candidates and ask
→ load node title/summary/prereq titles, wiki excerpt if authored,
source_hints if grounded, and prior .learn/chats/<id>.json if present
→ write .learn/chats/_active.json = {node_id, opened_at}
→ adopt the Tutor persona (agents/tutor.md) directly for this and
following turns — do not spawn a Task subagent per message (see
"Persona spawn format" note below)
→ after every exchange, append to .learn/chats/<id>.json (write-through;
there is no reliable session-end event to rely on otherwise)
→ tell the user: "/learn chat done" ends this session
IF route is chat done:
→ read .learn/chats/_active.json; if absent, say no chat is open
→ derive understanding_signal (confidence, misconceptions, notes) from
the full transcript and write it to .learn/chats/<id>.json
→ append node id to today's log/YYYY-MM-DD.json nodes_touched
(create the log skeleton if it doesn't exist yet, same as Coach does)
→ clear .learn/chats/_active.json
→ short debrief
Horizon buffer low means: count of nodes with status != mastered that have wiki authored and are on the planned path, with day_index ahead of "today", is less than profile.horizon_days.
Drift means Pace Analyst sets pace.drift = true (e.g. consecutive fails, actual_min >> planned_min, or user ratings "too hard" repeatedly).
Cold start procedure
- Confirm goal and rough level if missing:
- level:
beginner | intermediate | advanced (or free text stored as start_level)
- optional: minutes per day (default 45)
- Run:
node "${CLAUDE_PLUGIN_ROOT}/scripts/init-state.js" . --goal "GOAL" --level LEVEL --minutes 45
- Spawn Architect with:
- goal, level, minutes/day
- instruction to write
.learn/graph.json per schema
- reverse-plan from goal to prerequisites; order nodes for a multi-day path
- Spawn Domain Expert with the draft graph; apply critical fixes
- Spawn Learning Scientist to set:
- day batching (which nodes on day 1, 2, 3…)
- initial ease / SR defaults in
sr-queue.json (empty until first mastery)
pace.json initial nodes_per_day guess
- Spawn Author for nodes where
horizon.ready_node_ids should be filled (first N days of the ordered path). Each node → .learn/wiki/<id>.html and optional .learn/exercises/<id>/.
- Update
horizon.json with authored node ids and generated_through_day.
- Run:
node "${CLAUDE_PLUGIN_ROOT}/scripts/generate-dashboard.js" .
- Tell user Day 1 plan and open path for dashboard.
Persona spawn format
When spawning a subagent, load the matching agent file and include:
- Absolute path to cwd and
.learn/
- Relevant JSON state excerpts
- Exact files they may write
- "Return: short summary + list of files written"
Do not spawn personas that only chat. Every persona that mutates state must write valid JSON/HTML to disk.
Exception — Tutor (chat route): every other persona is a one-shot spawn → work → return summary. Live back-and-forth dialogue doesn't fit that contract — relaying each user message through a subagent spawn/continue would add a full round-trip per turn for no benefit, since the orchestrator is already conversational. For /learn chat, the orchestrator follows agents/tutor.md directly for the duration of the chat instead of spawning a subagent per message, writing through to .learn/chats/<id>.json after every exchange.
graphify / wiki content
If the user's environment has the graphify skill available, Author should use it for multi-page knowledge graphs on dense topics. Otherwise use templates/wiki-page.html as a single-file page with an embedded explainer section.
Interactive explainers must be self-contained (inline CSS/JS, no required CDN). Optional progressive enhancement with CDN is OK if offline still shows static content.
Codebase-grounded mode
If cwd has substantial source (not just .learn/):
- Architect may add
"grounded": true and "source_hints": ["path", ...] on nodes
- Author should Read those files and use real symbols in examples
- Assessor should prefer runnable exercises in-repo
Chat voice
- Short, concrete. Paths and next actions over essays.
- Coach owns encouragement; orchestrator stays operational.
- Never invent mastery; only mark
mastered after Assessor pass or explicit user override logged.
Failure modes
| Situation | Action |
|---|
| Corrupt JSON | Report file; offer reset of that file only |
| Author fails mid-buffer | Keep partial wiki; mark horizon honestly; retry on next run |
| User changes goal mid-course | Confirm; archive .learn → .learn-archive-<date>; re-init |
Empty /learn done | Ask what they completed before grading |
Chat left open (no chat done) | Next /learn done checks .learn/chats/_active.json; if set, lazily derive understanding_signal from whatever transcript exists before proceeding |
First-slice acceptance
Skeleton is correct when:
init-state.js creates valid .learn/ tree
- Example under
examples/llm-from-scratch has graph + wiki + openable dashboard
generate-dashboard.js rebuilds dashboard from JSON alone
- Commands + agents exist so a full Claude session can run cold start without inventing schema