MAMATHA EPILI / ENGINEERING & AI
Selected work

AI platform2026Open source

SkillForge

Three agents grade code against rubrics you author yourself

Stack

Frontend
  • Next.js 14 App Router playground
  • Angular 18 standalone components with Signals
  • TypeScript across both apps
  • Tailwind CSS
  • Monaco Editor
  • Sandboxed live preview
  • GSAP score dial, Framer Motion feedback drawer
  • Reactive Forms rubric and challenge editors
Backend & Data
  • Go 1.22 with Gin
  • OpenAPI generated from handler annotations
  • Supabase PostgreSQL with pgvector
  • Cosine retrieval through a SQL function
  • 768-dimension embeddings, L2-normalised
  • Three-agent evaluation pipeline
  • JSONB audit trail per submission
  • Row-level security, service-role key held server-side only

Problem

Rubric-grounded grading is only as good as the rubrics, and the prototype had no way to write them — the corpus was committed to the repository, so changing a criterion meant a code change and a redeploy. Grading criteria are content, not code, and whoever owns the subject matter should be able to author them.

What I built

  • An admin console for authoring challenges and skill rubrics, where saving a rubric embeds it and editing one re-embeds it, so a vector can never drift from the text it represents.
  • A Go assessment API with full CRUD over challenges and rubrics, dashboard aggregates and a health probe, its OpenAPI spec generated from the handler annotations so the documentation cannot fall behind the code.
  • The evaluation pipeline as a service: embed the submission, retrieve the closest rubrics by cosine similarity, run spec compliance, then logic, then a mentor that only asks questions, and weight the score 40/60 towards functional correctness.
  • A learner playground with an editor, a sandboxed preview, an animated score dial and a feedback drawer that stages each agent’s findings.
  • A full audit trail: every submission stores the retrieved rubrics, all three agent reports, any warnings, latency and the model names it ran against.
  • A static demo page with recorded pipeline responses, so the system can be read end to end without a database, an API key or a single network call.

Technical decisions & trade-offs

  • Vectors moved from a committed file into the database once rubrics became editable — retrieval is a SQL function over an indexed column, so authoring and search share one source of truth.
  • Embeddings are truncated to 768 dimensions and re-normalised, because only the full-width vector arrives normalised and cosine search assumes unit vectors. A width mismatch fails loudly rather than writing a corrupt row.
  • Submitted code is fenced and both code-facing agents are told to treat it as untrusted data; the mentor never sees the raw submission at all, only the structured reports, so there is no path from a submission to the agent that speaks to the learner.
  • Every step degrades rather than fails: lost retrieval means the agents run ungrounded and say so, one dead scoring agent means the survivor carries the score, and a failed write still returns the learner their feedback.
  • Model names, thresholds and top-k are configuration, not constants — providers retire models on a schedule, and that should be an environment change rather than a release.
  • The rubric label is embedded along with the rubric body, so retrieval can match on the name of a skill and not only on its description.

Challenges solved

  • A vector index on a small table quietly returned nothing while exact matches existed — approximate search partitions the space before there is enough data to partition, so the fix was to drop the index until the table earns it.
  • Keeping two frontends, a Go API and a SQL schema agreed on one contract: the generated spec and typed clients mirror the domain models, so a field rename surfaces at compile time instead of in a broken response.
  • The dashboard pass rate and the API’s own verdict came from two different places — a SQL aggregate and a configurable threshold — and could disagree. Documented as a constraint rather than papered over.
  • Grading without executing code is an honest limit, not a feature: the logic agent reasons about behaviour, and containerised test runs are written down as the next step rather than implied.

Outcome

Open source, and the version I would hand to someone else: the prototype proved the pipeline, this one makes the rubrics — the part that decides grading quality — something a subject expert can own without touching the codebase.

Permalink: https://www.mamathaepili.com/projects/skillforge