# udlhs/degreeguidance architecture

> Architecture diagram of the GitHub repository udlhs/degreeguidance, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/udlhs/degreeguidance
- Repository: https://github.com/udlhs/degreeguidance

## Overview

Degree Guidance is a Sri Lankan university-admissions decision aid. Students submit their A/L profile, receive deterministic eligibility results and transparent rankings, then may ask a conversational advisor grounded in course data and knowledge sources. Admins maintain the yearly cutoff dataset through handbook ingestion, review, and promotion. The README documents capabilities beyond the sampled implementation; links for those are limited to documented module paths, and the source excerpts do not show every router-to-service call.

Main entry points: [`core/db.py`](https://github.com/udlhs/degreeguidance/blob/main/core/db.py) (Postgres and pgvector), [`web/src/app/api/public/[...path]/route.ts`](https://github.com/udlhs/degreeguidance/blob/main/web/src/app/api/public/%5B...path%5D/route.ts) (Public API proxy), [`core/chat/orchestrator.py`](https://github.com/udlhs/degreeguidance/blob/main/core/chat/orchestrator.py) (Agent orchestrator), [`apps/api/routers/admin_ingestions.py`](https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/admin_ingestions.py) (Ingestion API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_student["Student guidance"]
  node_student_ui["Guidance interface<br/>[page.tsx]"]
  node_student_proxy["Public API proxy<br/>[route.ts]"]
  node_results["Guidance results<br/>[results-view.tsx]"]
  node_chat_ui["Advisor chat<br/>[chat-panel.tsx]"]
end

subgraph group_advisor["AI advisor"]
  node_orchestrator["Agent orchestrator<br/>[orchestrator.py]"]
  node_tools["Advisor tools<br/>[tools.py]"]
  node_retrieval["Knowledge retrieval<br/>[retrieval.py]"]
  node_gemini{{"Gemini"}}
end

subgraph group_admin["Admin data lifecycle"]
  node_admin_ui["Admin panel<br/>[page.tsx]"]
  node_admin_proxy["Admin BFF<br/>[route.ts]"]
  node_ingestion_api["Ingestion API"]
  node_queue["Arq queue<br/>[queue.py]"]
  node_extract_job["PDF extraction job<br/>[extract_pdf.py]"]
  node_ingestion_core["Ingestion processing<br/>[grid_extractor.py]"]
  node_cutoff_loader["Cutoff loader<br/>[ingest_zscores.py]"]
  node_worker_index["Knowledge indexing"]
end

subgraph group_platform["API and persistence"]
  node_eligibility_api["Eligibility API<br/>[eligibility.py]"]
  node_eligibility["Eligibility engine<br/>[engine.py]"]
  node_recommend_api["Recommendation API<br/>[recommendations.py]"]
  node_scoring["Ranking service<br/>[service.py]"]
  node_scoring_engine["Scoring engine<br/>[engine.py]"]
  node_chat_api["Chat API<br/>[chat.py]"]
  node_db[("Postgres and pgvector<br/>[db.py]")]
end

node_student(("Student"))
node_admin(("Administrator"))

node_student -->|"enters profile"| node_student_ui
node_student_ui -->|"requests guidance"| node_student_proxy
node_student_proxy -->|"forwards request"| node_eligibility_api
node_eligibility_api -->|"checks eligibility"| node_eligibility
node_eligibility -->|"queries cutoffs"| node_db
node_eligibility -->|"writes audit"| node_db
node_student_proxy -->|"requests ranking"| node_recommend_api
node_recommend_api -->|"ranks eligible courses"| node_scoring
node_scoring -->|"scores courses"| node_scoring_engine
node_scoring_engine -->|"returns ranking"| node_recommend_api
node_recommend_api -->|"loads scoring data"| node_db
node_eligibility_api -->|"returns results"| node_student_proxy
node_recommend_api -->|"returns ranking"| node_student_proxy
node_student_proxy -->|"supplies guidance"| node_results
node_student_ui -->|"opens advisor"| node_chat_ui
node_chat_ui -->|"sends question"| node_chat_api
node_chat_api -->|"runs agent"| node_orchestrator
node_orchestrator -->|"dispatches tools"| node_tools
node_tools -->|"searches knowledge"| node_retrieval
node_retrieval -->|"retrieves passages"| node_db
node_orchestrator -->|"sends prompt and tools"| node_gemini
node_gemini -->|"returns tool calls"| node_orchestrator
node_tools -->|"reads course data"| node_db
node_orchestrator -->|"returns response"| node_chat_api
node_admin -->|"manages handbooks"| node_admin_ui
node_admin_ui -->|"calls admin API"| node_admin_proxy
node_admin_proxy -->|"forwards request"| node_ingestion_api
node_ingestion_api -->|"enqueues extraction"| node_queue
node_queue -->|"dispatches job"| node_extract_job
node_extract_job -->|"extracts cutoff grid"| node_ingestion_core
node_ingestion_api -->|"stores review state"| node_db
node_admin_ui -.->|"uploads handbook"| node_ingestion_api
node_ingestion_api -->|"promotes reviewed data"| node_cutoff_loader
node_cutoff_loader -->|"writes cutoff records"| node_db
node_worker_index -->|"indexes knowledge"| node_db
node_admin_proxy -.->|"requests indexing"| node_worker_index

click node_student_ui "https://github.com/udlhs/degreeguidance/blob/main/web/src/app/(student)/page.tsx"
click node_student_proxy "https://github.com/udlhs/degreeguidance/blob/main/web/src/app/api/public/%5B...path%5D/route.ts"
click node_eligibility_api "https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/eligibility.py"
click node_eligibility "https://github.com/udlhs/degreeguidance/blob/main/core/eligibility/engine.py"
click node_recommend_api "https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/recommendations.py"
click node_scoring "https://github.com/udlhs/degreeguidance/blob/main/core/scoring/service.py"
click node_scoring_engine "https://github.com/udlhs/degreeguidance/blob/main/core/scoring/engine.py"
click node_results "https://github.com/udlhs/degreeguidance/blob/main/web/src/components/student/results-view.tsx"
click node_chat_ui "https://github.com/udlhs/degreeguidance/blob/main/web/src/components/student/chat-panel.tsx"
click node_chat_api "https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/chat.py"
click node_orchestrator "https://github.com/udlhs/degreeguidance/blob/main/core/chat/orchestrator.py"
click node_tools "https://github.com/udlhs/degreeguidance/blob/main/core/chat/tools.py"
click node_retrieval "https://github.com/udlhs/degreeguidance/blob/main/core/rag/retrieval.py"
click node_admin_ui "https://github.com/udlhs/degreeguidance/blob/main/web/src/app/admin/(panel)/ingestions/page.tsx"
click node_admin_proxy "https://github.com/udlhs/degreeguidance/blob/main/web/src/app/api/bff/%5B...path%5D/route.ts"
click node_ingestion_api "https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/admin_ingestions.py"
click node_queue "https://github.com/udlhs/degreeguidance/blob/main/apps/api/queue.py"
click node_extract_job "https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/extract_pdf.py"
click node_ingestion_core "https://github.com/udlhs/degreeguidance/blob/main/core/ingestion/grid_extractor.py"
click node_cutoff_loader "https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/ingest_zscores.py"
click node_db "https://github.com/udlhs/degreeguidance/blob/main/core/db.py"
click node_worker_index "https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/index_factsheets.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_student_ui,node_student_proxy,node_results,node_chat_ui toneBlue
class node_orchestrator,node_tools,node_retrieval,node_gemini toneAmber
class node_admin_ui,node_admin_proxy,node_ingestion_api,node_queue,node_extract_job,node_ingestion_core,node_cutoff_loader,node_worker_index toneMint
class node_eligibility_api,node_eligibility,node_recommend_api,node_scoring,node_scoring_engine,node_chat_api,node_db toneRose
class node_student,node_admin toneIndigo
```

## Components

### Student guidance

- [Guidance interface](https://github.com/udlhs/degreeguidance/blob/main/web/src/app/(student)/page.tsx): `web/src/app/(student)/page.tsx`
- [Public API proxy](https://github.com/udlhs/degreeguidance/blob/main/web/src/app/api/public/%5B...path%5D/route.ts): `web/src/app/api/public/[...path]/route.ts`
- [Guidance results](https://github.com/udlhs/degreeguidance/blob/main/web/src/components/student/results-view.tsx): `web/src/components/student/results-view.tsx`
- [Advisor chat](https://github.com/udlhs/degreeguidance/blob/main/web/src/components/student/chat-panel.tsx): `web/src/components/student/chat-panel.tsx`

### AI advisor

- [Agent orchestrator](https://github.com/udlhs/degreeguidance/blob/main/core/chat/orchestrator.py): `core/chat/orchestrator.py`
- [Advisor tools](https://github.com/udlhs/degreeguidance/blob/main/core/chat/tools.py): `core/chat/tools.py`
- [Knowledge retrieval](https://github.com/udlhs/degreeguidance/blob/main/core/rag/retrieval.py): `core/rag/retrieval.py`
- **Gemini**

### Admin data lifecycle

- [Admin panel](https://github.com/udlhs/degreeguidance/blob/main/web/src/app/admin/(panel)/ingestions/page.tsx): `web/src/app/admin/(panel)/ingestions/page.tsx`
- [Admin BFF](https://github.com/udlhs/degreeguidance/blob/main/web/src/app/api/bff/%5B...path%5D/route.ts): `web/src/app/api/bff/[...path]/route.ts`
- [Ingestion API](https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/admin_ingestions.py): `apps/api/routers/admin_ingestions.py`
- [Arq queue](https://github.com/udlhs/degreeguidance/blob/main/apps/api/queue.py): `apps/api/queue.py`
- [PDF extraction job](https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/extract_pdf.py): `apps/worker/jobs/extract_pdf.py`
- [Ingestion processing](https://github.com/udlhs/degreeguidance/blob/main/core/ingestion/grid_extractor.py): `core/ingestion/grid_extractor.py`
- [Cutoff loader](https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/ingest_zscores.py): `apps/worker/jobs/ingest_zscores.py`
- [Knowledge indexing](https://github.com/udlhs/degreeguidance/blob/main/apps/worker/jobs/index_factsheets.py): `apps/worker/jobs/index_factsheets.py`

### API and persistence

- [Eligibility API](https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/eligibility.py): `apps/api/routers/eligibility.py`
- [Eligibility engine](https://github.com/udlhs/degreeguidance/blob/main/core/eligibility/engine.py): `core/eligibility/engine.py`
- [Recommendation API](https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/recommendations.py): `apps/api/routers/recommendations.py`
- [Ranking service](https://github.com/udlhs/degreeguidance/blob/main/core/scoring/service.py): `core/scoring/service.py`
- [Scoring engine](https://github.com/udlhs/degreeguidance/blob/main/core/scoring/engine.py): `core/scoring/engine.py`
- [Chat API](https://github.com/udlhs/degreeguidance/blob/main/apps/api/routers/chat.py): `apps/api/routers/chat.py`
- [Postgres and pgvector](https://github.com/udlhs/degreeguidance/blob/main/core/db.py): `core/db.py`

### Other components

- **Student**
- **Administrator**

## Connections

- Student → Guidance interface: enters profile
- Guidance interface → Public API proxy: requests guidance
- Public API proxy → Eligibility API: forwards request
- Eligibility API → Eligibility engine: checks eligibility
- Eligibility engine → Postgres and pgvector: queries cutoffs
- Eligibility engine → Postgres and pgvector: writes audit
- Public API proxy → Recommendation API: requests ranking
- Recommendation API → Ranking service: ranks eligible courses
- Ranking service → Scoring engine: scores courses
- Scoring engine → Recommendation API: returns ranking
- Recommendation API → Postgres and pgvector: loads scoring data
- Eligibility API → Public API proxy: returns results
- Recommendation API → Public API proxy: returns ranking
- Public API proxy → Guidance results: supplies guidance
- Guidance interface → Advisor chat: opens advisor
- Advisor chat → Chat API: sends question
- Chat API → Agent orchestrator: runs agent
- Agent orchestrator → Advisor tools: dispatches tools
- Advisor tools → Knowledge retrieval: searches knowledge
- Knowledge retrieval → Postgres and pgvector: retrieves passages
- Agent orchestrator → Gemini: sends prompt and tools
- Gemini → Agent orchestrator: returns tool calls
- Advisor tools → Postgres and pgvector: reads course data
- Agent orchestrator → Chat API: returns response
- Administrator → Admin panel: manages handbooks
- Admin panel → Admin BFF: calls admin API
- Admin BFF → Ingestion API: forwards request
- Ingestion API → Arq queue: enqueues extraction
- Arq queue → PDF extraction job: dispatches job
- PDF extraction job → Ingestion processing: extracts cutoff grid
- Ingestion API → Postgres and pgvector: stores review state
- Admin panel → Ingestion API: uploads handbook
- Ingestion API → Cutoff loader: promotes reviewed data
- Cutoff loader → Postgres and pgvector: writes cutoff records
- Knowledge indexing → Postgres and pgvector: indexes knowledge
- Admin BFF → Knowledge indexing: requests indexing
