-
Notifications
You must be signed in to change notification settings - Fork 0
Features
Ramiro Cantu edited this page May 30, 2026
·
2 revisions
Catalog of what Gradient does, grouped by area, with the backing code and the
governing SPEC sections. Gradient is single-user, local-first, backend-only
(SPEC §C / V-D1): every feature is a JSON API (/api/v1/*), an MCP tutor seam,
or a scheduled job — there is no in-repo UI.
For how the AI features actually work, see Intelligence Layer. Each area below has a dedicated deep-dive page: Knowledge Base · Outline & Mastery · Question Capture · Anki · Tutor & MCP · Platform & Admin.
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| PDF notes ingestion | Drop <course-slug>/*.pdf in the inbox dir (or POST to the ingest endpoint); each page is rendered + vision-transcribed + mined for atomic facts |
kb/inbox.py, kb/pdf_ingest.py, api/v1/pdf.py
|
V-KB3, V-KB4 |
| Atomic facts | Self-contained factual claims extracted via structured output, deduped by content_hash per course |
kb/pdf_ingest.py, models/atomic_fact.py
|
V-KB4 |
| Embeddings + semantic recall | Nodes + content vectorized; candidate retrieval over cosine + similarity edges + content neighbours |
kb/embeddings.py, kb/recall.py, kb/similarity.py
|
V-E1, V-E2, V-L3, V-L6 |
| Automatic tagging | Grounded LLM4Tag categorizer: recall → pick → calibrate → tag to outline nodes |
kb/jobs.py, llm/grounded.py, llm/calibrator.py, kb/persist_tags.py
|
V-L3, V-L6, V69 |
| Manual-review queue | Low-confidence (< 0.5) tags are flagged, not dropped — surfaced for the user to curate | kb/persist_tags.py |
V-T3 |
| Notion write-out | One page per outline node, atomic facts as blocks; one-way Postgres→Notion replica | (Notion seam) | V-N1, V-N2 |
| KB read endpoints | Token-gated reads over the substrate: GET /concept-edges, /atomic-facts, /notion/pages, /pdf-sources (plain list[dict], no response_model) |
api/v1/kb_reads.py |
V-KB4 |
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| Schema-as-data outline | Upload an outline schema (e.g. AAMC) → materializes a recursive outline_nodes tree; re-upload restores it. No domain logic is privileged |
api/v1/outline.py, models/outline.py
|
V-O1..V-O4, V-O6 |
| Subtree rollup | Reads key on node_id + subtree membership (set, not sum) |
services/outline_subtree.py |
V-O1, V-O5 |
| Node search / labels | Substring search + >>-path resolution for tutor/read paths |
services/tutor/outline.py |
V-O5, V-M1 |
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| Capture ingress | Chrome-extension posts captured questions; token-guarded |
api/v1/*, services/ingest.py
|
§A, §I |
| Source adapters | Pluggable per-source readers (uworld, manual, web_qbank) sharing the extension_capture normalizer; the PDF-qset adapter was cut (T37) |
services/adapters/* |
§A |
| Question tagging | Same grounded path as facts, when the course is unambiguous | kb/jobs.py |
V-L3 |
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| Deck sync | Read AnkiConnect; derive review state, due dates; note-scoped tags | services/anki/sync.py |
V13, V75 |
| Tag parsing | Parse AnKing-style tags → node_id; schema-map source rows only |
services/anki/tag_parser.py |
V-T2, V-RB2 |
| Assignment unlock | Allowlisted writes (unsuspend, addTags, namespaced filtered decks); never mutates scheduling |
services/anki/* |
V13 |
| Review log | Append-only anki_card_reviews, incremental, local retention windows |
services/anki/retention.py |
V26, V27 |
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| MCP tutor seam | Data-exposure + persist tools only; Socratic reasoning host-side | services/tutor/* |
V-M1 |
| Discriminator factors | Persist tutor-derived discriminators (Postgres + Notion block + back-link) | services/tutor/* |
V-M1, P4 |
| Cognitive-safety rule | AI never generates primary active-recall questions / flashcards | — | V-M2 |
| Feature | What it does | Code | SPEC |
|---|---|---|---|
| Scheduler | APScheduler jobs: run_pdf_ingest, run_embed, run_grounded_tag, run_notion_sync, run_anki_sync, run_anki_assignment_unlock, run_anki_assignment_complete, run_anki_review; in-flight guards, V41 partial-failure. There is no run_categorizer or run_anki_topic_resolver — grounded tagging is the sole categorizer |
app/scheduler.py |
V41 |
| Token-cost logging | Reads OpenAI usage incl. cached_tokens; cache-hit accounting not inferred |
(LLM seams) | V-L1 |
| Admin / status API | Job status, run history, tag deletion | api/v1/admin* |
§I |
| Processing tier | Async jobs default to Flex (~50% off Standard) | config (OPENAI_SERVICE_TIER) |
V-L5 |
- Domain-blind core — MCAT/AAMC is one uploaded schema, not a privileged branch (V-O3).
-
Single LLM provider — OpenAI behind
services/llm/; mocked at the SDK boundary in tests (V16). -
Versioned everything —
embedding_version,extractor_versionstamp every derived row so a policy change is a clean re-run (V-E1, V-KB3). - Surface, don't drop — low-confidence outputs go to review, not the bin (V-T3).
Reference
Features
Design Notes