-
Notifications
You must be signed in to change notification settings - Fork 0
Roadmap
A phase-by-phase plan for growing the profilers from two standalone CLIs into a complete text-leveling toolkit for the EFL classroom — and, ultimately, the shared analysis engine behind the RubricMaker grading platform.
The through-line is one teacher question: "is this text right for this class, and if not, what has to change?" Each phase moves closer to answering it in one command, and closer to feature parity with what RubricMaker already does inside a full app (see RubricMaker Alignment).
Status legend — ✅ shipped · 🔨 in progress · 📋 planned · 💭 idea
This is a direction of travel, not a dated commitment. Phases are ordered by dependency: each builds on the one before.
Everything that exists today.
- ✅ Vocabulary profiler — CEFR (A1–C2), AWL, and NAWL banding, deterministic word-list matching, dependency-free Python 3.
- ✅ Grammar profiler — ~70 constructions across every major family, mapped to CEFR via the CEFR-J Grammar Profile, rule-based over a spaCy parse (no AI).
- ✅ File formats —
.txt,.md,.docx,.pdf, and stdin. - ✅ Two output modes — colour
prettyfor the terminal,jsonfor scripts, auto-selected by whether output is a TTY. - ✅ Claude Code plugins & skills — ask for a level in a Cowork session.
- ✅ Rebuilt, provenance-documented word lists and a citable grammar profile.
Outcome: you can profile any single text two ways, by hand or in chat.
Make the two profilers answer as one, and answer against a target.
- ✅ Unified difficulty report —
text_report.pyruns both profilers and prints one combined summary (vocabulary band + grammatical range + a blendedestimatedLevel), instead of two separate invocations. - ✅
--target-level B1— pass the class's level and the report flags what exceeds it: words above B1, constructions above B1, and a one-line verdict ("on level" / "reaches B2 — pre-teach 6 words, 2 structures"). - ✅ Coverage figure — "a B1 learner will already know ~92% of the running words," the single number teachers ask for most.
- ✅ Readability line — Flesch–Kincaid / Flesch Reading Ease, reported alongside — never instead of — the CEFR bands.
- ✅ Pre-teaching exports —
--export md|csv|flashcardswrite the above-target words and structures as a handout, spreadsheet, or RubricMaker-importable flashcard deck;--clozeturns the examples into fill-the-gap sentences that paste straight into a RubricMaker fill-the-gap question. - ✅ Free dictionary enrichment — decks ship with plain definitions,
phonetics and part-of-speech from the Free Dictionary API (no key),
backed by a persistent JSON lookup cache;
--pre-enrichprimes the cache for a whole class's word list in one polite, rate-limited pass. Offline or on a miss, the deck falls back to in-context sentences. - ✅ OLP-EN-CEFRJ wordlist merge —
build_wordlists.pygap-fills the CEFR lists from the open CEFR-J + Octanove profiles and emitslevels.json, so CEFR levels need no dictionary API.
RubricMaker parallel: its document analysis already reports vocabulary and grammar on one uploaded essay — Phase 1 gives the CLI the same combined view, and its deck import now reads the CLI's enriched output directly.
Scale from one text to the folder of candidate readings a teacher actually has.
- ✅ Batch mode —
--fileaccepts a directory, a glob (**for recursion), or a single file; every supported text (.txt/.md/.docx/.pdf) is profiled in one run, with unreadable files skipped — never fatal. - ✅ CSV / summary report — one row per text (filename, typical & reached vocabulary band, grammar range, % above target, fits verdict), ready for a spreadsheet.
- ✅ Rank & filter —
--sortranks the set by level (or band / word count / name);--min-level/--max-levelkeep only the texts in the band — so "which of these 20 articles suits B1?" is exactlyclass_profile.py --file essays/ --max-level B1. - ✅ Several classes at once —
--targets A2,B1,B2shows each text's fits / %-above verdict for every level side by side in one run. - ✅ Aggregate distribution — the pooled CEFR distribution over the whole set (typical band, 90%-coverage band, off-list share) — the dashboard's headline chart, from the command line.
- ✅ Vocabulary-list export by band —
--export-vocabdumps the distinct words in each CEFR band to CSV (vocab-A1.csv…vocab-C2.csv, plusvocab-off-list.csv), each row a word with its running occurrences and the texts it appears in — ready-made pre-teaching lists and glossaries. - ✅ Pre-teaching exports for the whole set —
--export md|csv|flashcardswrites one handout / worksheet / RubricMaker deck per text (reusing the Phase 1 writers), plus a combined class-wide deck with a level-keyed markdown index of every above-target word and the texts it came from (per level under--targets), and a set-level summary handout. - ✅
--pre-enrich— prime the dictionary cache from the whole folder's distinct vocabulary in one polite, rate-limited pass before exporting decks. - ✅ Plugin & skill —
class-profileships as a Claude Code plugin and skill like the other three tools, so "which of these suits B1?" works in a session. - ✅ Sample folder + CI golden checks — the repo bundles
sample-readings/(an A1→C2 gradient) and CI asserts the full CSV / JSON / export / band contracts against it end to end.
Why now: Use Cases 5 and 10 are one-command operations now — what used to be shell loops is first-class.
RubricMaker parallel: directly mirrors RubricMaker's Vocabulary Profile dashboard, which aggregates a class's texts into a CEFR distribution and exports vocabulary lists by CEFR band to CSV — Phase 2 produces the same artifact from the command line, plus ranking/filtering the dashboard doesn't have.
Stop only describing difficulty and start helping change it — the heart of the original VocabKitchen ("adjust a text to a target level").
- ✅ Above-target highlighting — the report lists every word and structure
above the target level, coloured in pretty mode, so a rewriter sees the
offenders at a glance (Use Case 6).
Already delivered by
text_report.py --target-leveland the band-tinted vocabulary view; the class profile ranks the offenders across a whole set. - ✅ Simpler-synonym suggestions —
text_report.py --suggestsuggests a lower-band alternative (purchase → buy (A1)) for each above-target word in the bundled curated list (WordLists/synonyms.csv, validated againstlevels.jsonbybuild_wordlists.py --check) — inline in the terminal, in JSON (aboveTarget.words[i].suggestion), and as a Simpler alternative column in the--export mdhandout. - ✅ Grammar gap report —
text_report.py --gap-reportlists the target-level constructions the text does not use yet — the "introduce these structures" checklist for graded-reader authors who need to add, not just remove — grouped by category in the terminal, in JSON (grammarGap.missing), and as a Constructions to introduce section in the--export mdhandout. Needs the grammar side; the class profile reuses the same per-text handouts. - ✅ Vocabulary interleaving —
class_profile.py --interleavebuilds a spaced-introduction schedule across a folder of readings: each reading introduces at most--new-words-per-readingnew above-target words (overflow is deferred to the next reading with room), words that recur later are flagged for spaced review, and words absent for two or more readings are marked due — written as a<set>-interleave-<LEVEL>.md|csvplan next to the handouts, so repeated readings introduce new words in a spaced pattern instead of all at once. - ✅ Watch mode —
text_report.py --watchkeeps re-profiling the--fileinput whenever it changes on disk (polls every second;--watch 0.2for faster) until Ctrl-C — the tight edit → re-check loop: save the graded reader and the report updates on the spot.
Why now: Phase 1 knows the target and Phase 2 handles many texts, so adaptation aids are the natural next step and the highest-value one for materials writers — all five Phase 3 items are now shipped.
RubricMaker parallel: RubricMaker's grammar linker checks target grammar per-criterion; the CLI's gap report is the authoring-side twin — what's missing versus what's present.
Speak the frameworks teachers are held accountable to, not just raw CEFR.
- ✅ Curriculum checklist — profile a text (or unit) against a supplied
checklist file (sections
[vocabulary]and[grammar]) and get a pass/fail coverage report: each required word present or missing (with its CEFR band when recognised), each required construction used or not,curriculum.passin JSON, a terminal checklist, and a Curriculum checklist section in the--export mdhandout — threaded throughclass_profile.py --export mdso a folder run shows which texts cover the unit's requirements, and through--export csvas a folder-level coverage grid (one row per text, one column per required item) — the same grid is mirrored as a Curriculum coverage section in the set-level summary handout so--export mdshows the grid too, and rides in the JSON report ascurriculumCoverage(items × rows × cells) so scripts can consume the pass/fail matrix without CSV parsing (Use Case 7). - ✅ Cambridge English exam mapping —
text_report.py --cambridgereports the matching Cambridge Qualification (A2 Key, B1 Preliminary, B2 First, C1 Advanced, C2 Proficiency) next to each band the report actually shows — vocabulary typical/reaches, grammar typical/reaches, estimated level — as an opt-in, in JSON (cambridge), the terminal, and the--export mdhandout. - ✅ CEFR Can-Do framing —
text_report.py --candoexpresses a text's demands as Can-Do descriptors, the language rubrics and self-assessment already use: one descriptor per band the report actually shows (reading/listening, interaction, spoken/written production) — opt-in, in JSON (cando), the terminal, and the--export mdhandout. With--target-level, each dimension also reportsaboveTarget: the descriptors the text demands beyond what the class is expected to do yet (every level strictly above the target up to the text's own band), shown as an Above the {target} target block — the same diff threads throughclass_profile.py --export mdso a folder run shows every text's Can-Do demands (and their gap against the class level) per handout. - 💭 Pluggable vocabulary profiles — first-class support for swapping in Oxford 3000/5000 or the Octanove C1/C2 profile via the existing one-word-per-line format, for teams standardised on a licensed list.
RubricMaker parallel: RubricMaker offers the exact same Cambridge English exam mapping and links criteria to standards (CCSS/NGSS, Dutch kerndoelen, CEFR Can-Do). Phase 4 makes the CLI produce output in those same frameworks, so a text profiled on the command line and a criterion graded in the app describe proficiency identically.
Close the loop: make these profilers the authoritative text-analysis backend RubricMaker calls, so both tools share one CEFR taxonomy and one implementation.
- 📋 Stable library / JSON contract — a documented, versioned output schema and an importable entry point (not just a CLI), so RubricMaker's document analysis (vocabulary & grammar checking on uploaded essays) can call the profilers directly instead of maintaining a parallel implementation.
- 📋 Per-criterion grammar pass/fail — emit results in the shape RubricMaker's grammar linker consumes for its per-criterion, apply-as-comment breakdown.
- 💭 Feed the Vocabulary Profile dashboard — batch-profile a class's essays and hand back the per-student CEFR vocabulary distribution the dashboard renders.
- 💭 Single source of truth for grammar — the CEFR-J Grammar Profile bundled here becomes the shared taxonomy both tools cite, so a construction is levelled the same way whether it's detected in a reading (CLI) or an essay (app).
- 📋 Free lookup swap in RubricMaker — replace
cambridgeApi.lookupWord(the paid Cambridge Dictionary API) with the free stack the CLI now uses: CEFR levels from the bundled CEFR-J /levels.json, definitions + phonetics from the Free Dictionary API, sharing the same cache format so teacher lookups and deck exports use one warmed cache. - 📋 Offline dictionary fallback — bundle Open English WordNet (CC BY 4.0) so definitions ship even with no network, writing results into the same lookup cache — the final layer that makes enrichment fully offline-capable.
- 📋 Import RubricMaker vocabulary lists into
--pre-enrich— read a class's vocabulary-list export (CSV/JSON) directly, so the cache is primed from the app's own data without reformatting.
Why last: it depends on the combined report (Phase 1), the framework alignment (Phase 4), and a proven detection surface — but it's the destination that makes the whole roadmap coherent: one leveling engine, two front ends (a CLI for materials prep, a web app for grading).
Phase 0 two profilers, one text ✅ shipped
│
Phase 1 one combined verdict + target ✅ shipped
│
Phase 2 many texts, CSV, by-band export ✅ shipped → answers "which of these?"
│
Phase 3 highlight + suggest + gaps ✅ 🔨 → answers "what do I change?"
│
Phase 4 Cambridge / curriculum / Can-Do → answers "in my framework"
│
Phase 5 shared engine for RubricMaker → one taxonomy, two front ends
Already-shipped groundwork that makes this realistic: a data-driven design (word lists and the grammar profile are swappable files, not hard-coded), a stable JSON output the tests freeze, and a no-AI, rule-based core that is deterministic and auditable — the same principles RubricMaker's own analysis is built on.
- Use Cases — the scenarios each phase improves.
- RubricMaker Alignment — the feature-by-feature map these phases converge on.
Vocabkitchen CLI — vocabulary & grammar profilers for the EFL classroom. CEFR-anchored, rule-based, no AI. · Companion to RubricMaker.