Skip to content

Commit b88336e

Browse files
willwearingclaude
andauthored
feat: academy-first CLI/MCP workflow and stronger quality gate (#114)
* feat: academy-first CLI/MCP workflow and stronger quality gate Most agent-authored courses should start as an academy — a connected curriculum of one or more courses — not a single course file. This makes that the default path across CLI, MCP, backend auth, and the runbook. - Add `graspful create academy` CLI command and `graspful_create_academy` MCP tool backed by shared `scaffoldAcademyObject`. - Add `graspful_import_academy` MCP tool and `graspful import` support for academy manifests with `--course-dir` resolution and per-course publish. - Allow API-key auth on `/orgs/:orgId/academies` by swapping `SupabaseAuthGuard` for `JwtOrApiKeyGuard` so the CLI can import academies without a browser session. - Replace the weak `cross_concept_coverage` quality check with `problem_teaching_alignment`: problems must reference material introduced in the current KP, earlier KPs, or prerequisite concepts. - Add advisory `kp_atomicity` warning that flags KP instructions with long parallel lists (6+ items) as likely teaching multiple facts. - Surface warnings in `graspful review` output and analytics. - Bump default KP stub count from 2 to 3 and teach the brand scaffold to take an optional `--topic` for specific landing copy. - Optimistic quiz and section-exam UI: advance on submit via `startTransition`, show a "Saving answer..." indicator, and roll back on failure. Covered by new Vitest cases. - Playwright config now builds the backend before starting it and raises the timeout to 120s so live e2e runs are reproducible. - Add end-to-end Playwright spec that scaffolds, imports, and publishes an academy through the real CLI against a live backend. - Refresh AGENTS.md, CLAUDE.md, README.md, docs/adding-a-course.md, and per-package READMEs so the academy-first workflow is canonical. - Rewrite `posthog-use-case-selling.yaml` to pass the new teaching alignment and atomicity checks. - Check in draft plan for the wrong-answer remediation loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: loosen teaching-alignment check to skip stubs and whole-KP drift Harden checkProblemTeachingAlignment against false positives so a single lexically drifted problem in an otherwise aligned KP no longer blocks the review gate. Two changes: - Skip the check when the teaching path has fewer than 8 distinct stems. Stub fixtures and in-progress drafts effectively have nothing to judge against and should not be punished by a content-quality gate. - Only fail a KP when every judgable problem is off-topic. A drifted single problem is a content-author nit, not a gate violation. Also extracts the alignment ignore list to a module-level constant for clarity and updates tests to cover the new whole-KP-drift behavior plus stub-fixture immunity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: align e2e test course fixture with stricter teaching-alignment check The publish-draft-course e2e test was failing because its minimal course YAML had stub-style instruction and workedExample text that shared no vocabulary with the problems. The new problem_teaching_alignment check correctly flagged the KPs as content the instruction doesn't teach, so publish returned passed=false. Update the fixture so instruction and worked example actually teach the material the problems test — arithmetic addition, Rayleigh scattering, water chemistry (concept-alpha) and addition, Earth's orbit, chemical symbols (concept-beta). This is the canonical fix: the fixture should model a real well-authored course, not a content-quality workaround. Also clean up a set of stale planning docs that were already removed in the working tree. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c1e1405 commit b88336e

50 files changed

Lines changed: 2542 additions & 17189 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ If MCP is already configured, you have these tools available — no CLI needed:
4141

4242
| Tool | Auth? | Description |
4343
|------|:---:|-------------|
44+
| `graspful_create_academy` | No | Generate academy manifest YAML |
4445
| `graspful_scaffold_course` | No | Generate course YAML skeleton |
4546
| `graspful_fill_concept` | No | Add KPs and problems to a concept |
4647
| `graspful_validate` | No | Validate YAML against schema |
47-
| `graspful_review_course` | No | Run 10 quality checks |
48+
| `graspful_review_course` | No | Run 10 quality checks, including teaching alignment |
4849
| `graspful_describe_course` | No | Course statistics |
4950
| `graspful_create_brand` | No | Generate brand YAML |
51+
| `graspful_import_academy` | **Yes** | Import academy manifest + course YAMLs (set `GRASPFUL_API_KEY` first) |
5052
| `graspful_import_course` | **Yes** | Import course to platform (set `GRASPFUL_API_KEY` first) |
5153
| `graspful_publish_course` | **Yes** | Publish a draft course (set `GRASPFUL_API_KEY` first) |
5254
| `graspful_import_brand` | **Yes** | Import brand config (set `GRASPFUL_API_KEY` first) |
@@ -73,38 +75,44 @@ The workflow is: scaffold -> fill -> validate -> review -> import.
7375

7476
**Before writing any YAML**, follow the detailed runbook in `docs/adding-a-course.md`. Key steps:
7577
1. Gather source material (official docs, syllabi, PDFs — not marketing copy)
76-
2. Decide: single course or academy with multiple courses
77-
3. Build the prerequisite graph (roots -> trunk -> branches -> leaves)
78-
4. Write the YAML skeleton (graph first, content second)
79-
5. Fill concepts one at a time
80-
6. Validate and review
78+
2. Model it as an academy first, even if it starts with one course
79+
3. Decompose the academy into foundations -> structures -> operations -> applied judgment
80+
4. Build the prerequisite graph (roots -> trunk -> branches -> leaves)
81+
5. Write the YAML skeleton (graph first, content second)
82+
6. Spend a cycle on the academy landing page so the promise and proof are specific to the learner
83+
7. Fill concepts one at a time
84+
8. Validate and review
8185

8286
```bash
83-
# 1. Scaffold the knowledge graph
87+
# 1. Scaffold the academy shell
88+
graspful create academy --topic "Your Topic" -o academy.yaml
89+
90+
# 2. Scaffold the first course knowledge graph
8491
graspful create course --topic "Your Topic" --hours 10 -o course.yaml
8592

86-
# 2. Fill each concept with knowledge points and problems
93+
# 3. Fill each concept with knowledge points and problems
8794
graspful fill concept course.yaml <concept-id>
8895

89-
# 3. Validate after every edit
96+
# 4. Validate after every edit
9097
graspful validate course.yaml
9198

92-
# 4. Review — must score 10/10 to publish
99+
# 5. Review — must score 10/10 to publish
93100
graspful review course.yaml
94101

95-
# 5. Import and publish
96-
graspful import course.yaml --org <org-slug> --publish
102+
# 6. Import and publish
103+
graspful import academy.yaml --org <org-slug> --course-dir . --publish
97104
```
98105

99106
Or with MCP tools:
100107

101108
```
109+
graspful_create_academy(topic: "Your Topic")
102110
graspful_scaffold_course(topic: "Your Topic", estimatedHours: 10)
103111
-> edit the YAML
104112
graspful_fill_concept(yaml: "...", conceptId: "concept-id")
105113
graspful_validate(yaml: "...")
106114
graspful_review_course(yaml: "...")
107-
graspful_import_course(yaml: "...", org: "org-slug", publish: true)
115+
graspful_import_academy(manifestYaml: "...", courseYamls: { "courses/course.yaml": "..." }, org: "org-slug", publish: true)
108116
```
109117

110118
### Images, Videos, Links in Course Content
@@ -161,12 +169,18 @@ When building a course from a PDF or document:
161169
4. For visual content (photos, diagrams, comparisons), find or request publicly accessible image URLs and use `image` content blocks
162170
5. Do not copy-paste prose verbatim — rewrite for the lesson pattern (instruction -> worked example -> problems)
163171

164-
### Step 4: Brand (optional)
172+
### Step 4: Brand and landing page
173+
174+
Treat the landing page as part of the academy build:
175+
176+
- the copy must describe the actual learner, outcome, and curriculum promise
177+
- the page should explain why this academy exists and why a learner should trust it
178+
- generic placeholder niche copy is not sufficient
165179

166180
Create a white-label landing page and theme:
167181

168182
```bash
169-
graspful create brand --niche tech --name "My Academy" --org my-org -o brand.yaml
183+
graspful create brand --niche tech --topic "Your Topic" --name "My Academy" --org my-org -o brand.yaml
170184
graspful import brand.yaml
171185
```
172186

CLAUDE.md

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ If MCP is already configured, you have these tools available — no CLI needed:
4040

4141
| Tool | Auth? | Description |
4242
|------|:---:|-------------|
43+
| `graspful_create_academy` | No | Generate academy manifest YAML |
4344
| `graspful_scaffold_course` | No | Generate course YAML skeleton |
4445
| `graspful_fill_concept` | No | Add KPs and problems to a concept |
4546
| `graspful_validate` | No | Validate YAML against schema |
46-
| `graspful_review_course` | No | Run 10 quality checks |
47+
| `graspful_review_course` | No | Run 10 quality checks, including teaching alignment |
4748
| `graspful_describe_course` | No | Course statistics |
4849
| `graspful_create_brand` | No | Generate brand YAML (required — every org needs a brand) |
50+
| `graspful_import_academy` | **Yes** | Import academy manifest + course YAMLs (set `GRASPFUL_API_KEY` first) |
4951
| `graspful_import_course` | **Yes** | Import course to platform (set `GRASPFUL_API_KEY` first) |
5052
| `graspful_publish_course` | **Yes** | Publish a draft course (set `GRASPFUL_API_KEY` first) |
5153
| `graspful_import_brand` | **Yes** | Import brand config — required for site to work (set `GRASPFUL_API_KEY` first) |
@@ -72,38 +74,44 @@ The workflow is: scaffold -> fill -> validate -> review -> import.
7274

7375
**Before writing any YAML**, follow the detailed runbook in `docs/adding-a-course.md`. Key steps:
7476
1. Gather source material (official docs, syllabi, PDFs — not marketing copy)
75-
2. Decide: single course or academy with multiple courses
76-
3. Build the prerequisite graph (roots -> trunk -> branches -> leaves)
77-
4. Write the YAML skeleton (graph first, content second)
78-
5. Fill concepts one at a time
79-
6. Validate and review
77+
2. Model it as an academy first, even if it starts with one course
78+
3. Decompose the academy into foundations -> structures -> operations -> applied judgment
79+
4. Build the prerequisite graph (roots -> trunk -> branches -> leaves)
80+
5. Write the YAML skeleton (graph first, content second)
81+
6. Spend a cycle on the academy landing page so the promise and proof are specific to the learner
82+
7. Fill concepts one at a time
83+
8. Validate and review
8084

8185
```bash
82-
# 1. Scaffold the knowledge graph
86+
# 1. Scaffold the academy shell
87+
graspful create academy --topic "Your Topic" -o academy.yaml
88+
89+
# 2. Scaffold the first course knowledge graph
8390
graspful create course --topic "Your Topic" --hours 10 -o course.yaml
8491

85-
# 2. Fill each concept with knowledge points and problems
92+
# 3. Fill each concept with knowledge points and problems
8693
graspful fill concept course.yaml <concept-id>
8794

88-
# 3. Validate after every edit
95+
# 4. Validate after every edit
8996
graspful validate course.yaml
9097

91-
# 4. Review — must score 10/10 to publish
98+
# 5. Review — must score 10/10 to publish
9299
graspful review course.yaml
93100

94-
# 5. Import and publish
95-
graspful import course.yaml --org <org-slug> --publish
101+
# 6. Import and publish
102+
graspful import academy.yaml --org <org-slug> --course-dir .
96103
```
97104

98105
Or with MCP tools:
99106

100107
```
108+
graspful_create_academy(topic: "Your Topic")
101109
graspful_scaffold_course(topic: "Your Topic", estimatedHours: 10)
102110
-> edit the YAML
103111
graspful_fill_concept(yaml: "...", conceptId: "concept-id")
104112
graspful_validate(yaml: "...")
105113
graspful_review_course(yaml: "...")
106-
graspful_import_course(yaml: "...", org: "org-slug", publish: true)
114+
graspful_import_academy(manifestYaml: "...", courseYamls: { "courses/course.yaml": "..." }, org: "org-slug", publish: true)
107115
```
108116

109117
### Images, Videos, Links in Course Content
@@ -160,7 +168,7 @@ When building a course from a PDF or document:
160168
4. For visual content (photos, diagrams, comparisons), find or request publicly accessible image URLs and use `image` content blocks
161169
5. Do not copy-paste prose verbatim — rewrite for the lesson pattern (instruction -> worked example -> problems)
162170

163-
### Step 4: Create or update the brand
171+
### Step 4: Create or update the academy landing page and brand
164172

165173
Every org needs a brand for the site to work. Registration creates a minimal default,
166174
but you should update it with content relevant to the course topic.
@@ -169,13 +177,19 @@ Use `graspful_create_brand` to generate a brand YAML tailored to the course topi
169177
then import it with `graspful_import_brand`. This updates the landing page headline,
170178
features, and SEO to match the actual course content.
171179

180+
Important:
181+
182+
- do not leave the landing page as generic niche filler
183+
- the page should name the learner, the outcome, the curriculum shape, and the proof for why this academy is worth joining
184+
- treat landing-page authoring as part of the academy build, not post-launch polish
185+
172186
If the org already has a brand (from registration), importing a new one updates it
173187
in place (upsert by slug).
174188

175189
Create a white-label landing page and theme:
176190

177191
```bash
178-
graspful create brand --niche tech --name "My Academy" --org my-org -o brand.yaml
192+
graspful create brand --niche tech --topic "Your Topic" --name "My Academy" --org my-org -o brand.yaml
179193
graspful import brand.yaml
180194
```
181195

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
# Graspful
22

3-
> Create adaptive learning courses with AI agents. Launch in minutes.
3+
> Create adaptive learning academies and courses with AI agents. Launch in minutes.
44
55
## What Is Graspful?
66

7-
Graspful is an agent-first course creation platform. Courses are defined as YAML files with knowledge graphs, validated by schema, and imported via CLI or MCP server -- no UI clicking required. Agents (or humans) scaffold a course, fill in content concept by concept, run quality checks, and publish. The platform handles the rest: adaptive diagnostics, mastery-based progression, spaced repetition, white-label landing pages, and Stripe billing.
7+
Graspful is an agent-first academy creation platform. Academies and courses are defined as YAML files with knowledge graphs, validated by schema, and imported via CLI or MCP server -- no UI clicking required. Agents (or humans) scaffold an academy, break it into prerequisite-aware courses, fill in content concept by concept, run quality checks, and publish. The platform handles the rest: adaptive diagnostics, mastery-based progression, spaced repetition, white-label landing pages, and Stripe billing.
88

99
## How It Works
1010

11-
1. **Scaffold** -- `graspful create course --topic "CKA Exam"` generates the knowledge graph skeleton
12-
2. **Fill** -- `graspful fill concept course.yaml networking` adds KPs and practice problems
13-
3. **Review** -- `graspful review course.yaml` runs 10 quality checks
14-
4. **Import** -- `graspful import course.yaml --org k8s-cert --publish` goes live
15-
5. **Brand** -- `graspful create brand --niche "Kubernetes"` generates the landing page
11+
1. **Scaffold academy** -- `graspful create academy --topic "CKA Exam"` generates the academy shell
12+
2. **Scaffold courses** -- `graspful create course --topic "Cluster Networking"` generates each course graph
13+
3. **Fill** -- `graspful fill concept course.yaml networking` adds KPs and practice problems
14+
4. **Review** -- `graspful review course.yaml` runs 10 quality checks, including whether problems only assess taught material
15+
5. **Import** -- `graspful import academy.yaml --org k8s-cert --course-dir . --publish` goes live
16+
6. **Brand** -- `graspful create brand --niche "Kubernetes" --topic "CKA Exam"` generates the landing page that actually sells the academy
1617

17-
Two YAMLs (course + brand) produce one live product with adaptive learning, spaced repetition, and Stripe billing.
18+
Three YAMLs (academy + courses + brand) produce one live product with adaptive learning, spaced repetition, and Stripe billing.
1819

1920
## Quick Start
2021

2122
```bash
2223
npx @graspful/cli init
2324
# opens browser auth, then saves an API key locally
2425
graspful register --email you@example.com
25-
graspful create course --scaffold-only --topic "Your Topic" -o course.yaml
26+
graspful create academy --topic "Your Topic" -o academy.yaml
27+
graspful create course --topic "Foundations" -o courses/foundations.yaml
2628
```
2729

2830
## Tech Stack
@@ -58,11 +60,12 @@ graspful/
5860
|---------|:---:|-------------|
5961
| `graspful register` | No | Create account + API key via browser auth |
6062
| `graspful login` | No | Authenticate with existing credentials |
63+
| `graspful create academy` | No | Generate academy manifest skeleton |
6164
| `graspful create course` | No | Generate course YAML skeleton |
6265
| `graspful create brand` | No | Generate brand YAML with theme presets |
6366
| `graspful fill concept` | No | Add KPs and problems to a concept |
6467
| `graspful validate` | No | Offline schema + DAG validation |
65-
| `graspful review` | No | 10 mechanical quality checks |
68+
| `graspful review` | No | 10 mechanical quality checks, including teaching alignment |
6669
| `graspful describe` | No | Course statistics |
6770
| `graspful import` | **Yes** | Push YAML to Graspful instance |
6871
| `graspful publish` | **Yes** | Publish a draft course |
@@ -96,12 +99,14 @@ Or manually add to your MCP config:
9699
| Tool | Auth? | Description |
97100
|------|:---:|-------------|
98101
| `graspful_scaffold_course` | No | Generate course YAML skeleton |
102+
| `graspful_create_academy` | No | Generate academy manifest scaffold |
99103
| `graspful_fill_concept` | No | Add KPs and problems to a concept |
100104
| `graspful_validate` | No | Validate YAML against schema |
101-
| `graspful_review_course` | No | Run 10 quality checks |
105+
| `graspful_review_course` | No | Run 10 quality checks, including teaching alignment |
102106
| `graspful_describe_course` | No | Course statistics |
103107
| `graspful_create_brand` | No | Generate brand YAML |
104108
| `graspful_import_course` | **Yes** | Import course to platform |
109+
| `graspful_import_academy` | **Yes** | Import academy manifest plus course YAMLs |
105110
| `graspful_publish_course` | **Yes** | Publish a draft course |
106111
| `graspful_import_brand` | **Yes** | Import brand config |
107112
| `graspful_list_courses` | **Yes** | List org courses |

0 commit comments

Comments
 (0)