Note: These are different from Risk Alerts above. This chart shows pure retention probability, while Risk Alerts combine retention with GPA and completion metrics.
+
>
}
/>
diff --git a/codebenders-dashboard/components/glossary-metric-entry-link.tsx b/codebenders-dashboard/components/glossary-metric-entry-link.tsx
new file mode 100644
index 0000000..23f2ee3
--- /dev/null
+++ b/codebenders-dashboard/components/glossary-metric-entry-link.tsx
@@ -0,0 +1,24 @@
+"use client"
+
+import Link from "next/link"
+import {
+ metricGlossaryEntryHref,
+ type MetricGlossarySlug,
+} from "@/lib/glossary-constants"
+
+const LINK_CLASS =
+ "text-primary underline-offset-4 hover:underline text-xs font-medium"
+
+interface GlossaryMetricEntryLinkProps {
+ slug: MetricGlossarySlug
+}
+
+export function GlossaryMetricEntryLink({ slug }: GlossaryMetricEntryLinkProps) {
+ return (
+
+ )
+}
diff --git a/codebenders-dashboard/components/readiness-assessment-chart.tsx b/codebenders-dashboard/components/readiness-assessment-chart.tsx
index 6f580f5..13c6650 100644
--- a/codebenders-dashboard/components/readiness-assessment-chart.tsx
+++ b/codebenders-dashboard/components/readiness-assessment-chart.tsx
@@ -3,8 +3,9 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
-import { AlertCircle, TrendingUp, TrendingDown, Users, Target, AlertTriangle } from 'lucide-react';
+import { AlertCircle, TrendingUp, Users, Target, AlertTriangle } from 'lucide-react';
import { InfoPopover } from '@/components/info-popover';
+import { GlossaryMetricEntryLink } from '@/components/glossary-metric-entry-link';
interface ReadinessData {
summary: {
@@ -187,7 +188,11 @@ export function ReadinessAssessmentChart({ data, isLoading, error }: ReadinessAs
Student readiness categorization
- AI-powered assessment analyzing student preparation, engagement, and success indicators. High readiness indicates students are well-positioned for success.
+
+ AI-powered assessment analyzing student preparation, engagement, and success indicators. High readiness
+ indicates students are well-positioned for success.
+
+
diff --git a/codebenders-dashboard/content/metric-glossary.md b/codebenders-dashboard/content/metric-glossary.md
index 2c733ec..c9ad94b 100644
--- a/codebenders-dashboard/content/metric-glossary.md
+++ b/codebenders-dashboard/content/metric-glossary.md
@@ -1,6 +1,6 @@
# Metric glossary
-Single source of truth for dashboard KPI definitions. Each section is keyed by its URL anchor (e.g. `/glossary#overall-retention-rate`). Cross-walks are indicative — institutions should confirm against their PDP documentation, IPEDS submission manuals, and state reporting rules.
+Single source of truth for dashboard KPIs and chart views. Each section is keyed by its URL anchor (e.g. `/glossary#overall-retention-rate`). Cross-walks are indicative — institutions should confirm against their PDP documentation, IPEDS submission manuals, and state reporting rules.
---
@@ -49,3 +49,39 @@ Single source of truth for dashboard KPI definitions. Each section is keyed by i
**IPEDS:** Conceptually related to success rates and progression, but IPEDS collects many distinct measures (e.g., completions by award) — do not assume identity without a written cross-walk.
**State compliance:** Often parallels “success rate” or “credit completion ratio” in performance funding models; verify denominator rules match your state formula.
+
+---
+
+## risk-alert-distribution
+
+**Plain English:** Pie chart of students grouped by **composite risk alert** band (LOW, MODERATE, HIGH, URGENT) used for triage — not the same as the retention-probability-only funnel chart.
+
+**PDP / analysis-ready:** Counts come from `at_risk_alert` on `student_level_with_predictions` after dashboard filters. The composite rule combines retention probability, GPA bands, course completion, and credit progress (see in-chart tooltip and methodology).
+
+**IPEDS:** No direct IPEDS collection; analogous to internal early-alert or “at risk” population counts if your institution defines them similarly.
+
+**State compliance:** Operational metric; if reported externally, align labels and thresholds with your state’s definitions and suppress small cells where required.
+
+---
+
+## retention-risk-funnel
+
+**Plain English:** Horizontal bar chart of students by **model retention risk category** (Critical / High / Moderate / Low) from predicted retention probability alone.
+
+**PDP / analysis-ready:** Buckets are derived from `retention_probability` (XGBoost) using fixed cut points on `student_level_with_predictions`.
+
+**IPEDS:** Not an IPEDS measure; related conceptually to retention outcome reporting but this view is **predictive**, not audited cohort outcomes.
+
+**State compliance:** Use for advising and planning; do not substitute for official retention rates in external reporting without documentation.
+
+---
+
+## readiness-assessment
+
+**Plain English:** PDP-aligned **readiness index** — composite score and High / Medium / Low bands summarizing academic, engagement, and ML-risk components for the filtered cohort.
+
+**PDP / analysis-ready:** Scores and levels are computed server-side (see `/api/dashboard/readiness` and methodology) from fields on `student_level_with_predictions` and related logic.
+
+**IPEDS:** No IPEDS analog; closest institutional parallels are internal “student success” or “momentum” indices if your IR office publishes them.
+
+**State compliance:** Treat as an internal diagnostic; confirm any export or public use against institutional policy and small-N rules.
diff --git a/codebenders-dashboard/lib/__tests__/metric-glossary-coverage.test.ts b/codebenders-dashboard/lib/__tests__/metric-glossary-coverage.test.ts
index debf689..de47fd7 100644
--- a/codebenders-dashboard/lib/__tests__/metric-glossary-coverage.test.ts
+++ b/codebenders-dashboard/lib/__tests__/metric-glossary-coverage.test.ts
@@ -1,26 +1,19 @@
import { describe, expect, it } from "vitest"
-import {
- DASHBOARD_KPI_GLOSSARY_SLUGS,
- GLOSSARY_TOPIC_SECTIONS,
-} from "@/lib/glossary-constants"
+import { GLOSSARY_TOPIC_SECTIONS, METRIC_GLOSSARY_INDEX_SLUGS } from "@/lib/glossary-constants"
import { parseGlossaryEntries, readMetricGlossaryMarkdown } from "@/lib/metric-glossary"
-describe("metric glossary coverage (#105)", () => {
- it("includes every dashboard KPI slug in metric-glossary.md", () => {
+describe("metric glossary coverage (#105 / #124)", () => {
+ it("includes every indexed slug in metric-glossary.md", () => {
const md = readMetricGlossaryMarkdown()
const entries = parseGlossaryEntries(md)
- for (const slug of DASHBOARD_KPI_GLOSSARY_SLUGS) {
+ for (const slug of METRIC_GLOSSARY_INDEX_SLUGS) {
expect(entries[slug], `missing ## ${slug} in content/metric-glossary.md`).toBeTruthy()
expect(entries[slug]!.length).toBeGreaterThan(20)
}
})
- it("topic sections list each KPI slug exactly once", () => {
- const listed = GLOSSARY_TOPIC_SECTIONS.flatMap((t) => [...t.slugOrder])
- expect(listed.length).toBe(DASHBOARD_KPI_GLOSSARY_SLUGS.length)
- for (const slug of DASHBOARD_KPI_GLOSSARY_SLUGS) {
- const n = listed.filter((s) => s === slug).length
- expect(n, `slug ${slug} should appear once in GLOSSARY_TOPIC_SECTIONS`).toBe(1)
- }
+ it("topic sections list each indexed slug exactly once in index order", () => {
+ const listedSlugs = GLOSSARY_TOPIC_SECTIONS.flatMap((t) => [...t.slugOrder])
+ expect(listedSlugs).toEqual([...METRIC_GLOSSARY_INDEX_SLUGS])
})
})
diff --git a/codebenders-dashboard/lib/glossary-constants.ts b/codebenders-dashboard/lib/glossary-constants.ts
index 2a86003..e0295c0 100644
--- a/codebenders-dashboard/lib/glossary-constants.ts
+++ b/codebenders-dashboard/lib/glossary-constants.ts
@@ -3,12 +3,12 @@
export const GLOSSARY_HREF = "/glossary" as const
/**
- * Source of truth for topic groupings and KPI slug order on the glossary page.
- * `DASHBOARD_KPI_GLOSSARY_SLUGS` is derived from this list; every `##` section in
- * `content/metric-glossary.md` must stay in sync (see
- * `lib/__tests__/metric-glossary-coverage.test.ts`).
+ * Source of truth for topic groupings on the glossary page.
+ * `METRIC_GLOSSARY_INDEX_SLUGS` (and deprecated `DASHBOARD_KPI_GLOSSARY_SLUGS`) are
+ * derived from this list; every `##` section in `content/metric-glossary.md` must
+ * stay in sync (see `lib/__tests__/metric-glossary-coverage.test.ts`).
*/
-const GLOSSARY_TOPIC_SECTIONS_RAW = [
+const METRIC_GLOSSARY_TOPIC_SECTIONS_SOURCE = [
{
id: "retention",
label: "Retention, risk & predictions",
@@ -23,19 +23,38 @@ const GLOSSARY_TOPIC_SECTIONS_RAW = [
label: "Completion & course success",
slugOrder: ["avg-course-completion"] as const,
},
+ {
+ id: "charts",
+ label: "Charts & composite views",
+ slugOrder: [
+ "risk-alert-distribution",
+ "retention-risk-funnel",
+ "readiness-assessment",
+ ] as const,
+ },
] as const
-export type DashboardKpiGlossarySlug =
- (typeof GLOSSARY_TOPIC_SECTIONS_RAW)[number]["slugOrder"][number]
+export type MetricGlossarySlug =
+ (typeof METRIC_GLOSSARY_TOPIC_SECTIONS_SOURCE)[number]["slugOrder"][number]
+
+/** @deprecated Use `MetricGlossarySlug` */
+export type DashboardKpiGlossarySlug = MetricGlossarySlug
+
+export function metricGlossaryEntryHref(slug: MetricGlossarySlug): string {
+ return `${GLOSSARY_HREF}#${slug}`
+}
+
+export const METRIC_GLOSSARY_INDEX_SLUGS: readonly MetricGlossarySlug[] =
+ METRIC_GLOSSARY_TOPIC_SECTIONS_SOURCE.flatMap((topic) => [...topic.slugOrder])
-export const DASHBOARD_KPI_GLOSSARY_SLUGS: readonly DashboardKpiGlossarySlug[] =
- GLOSSARY_TOPIC_SECTIONS_RAW.flatMap((topic) => [...topic.slugOrder])
+/** @deprecated Use `METRIC_GLOSSARY_INDEX_SLUGS` */
+export const DASHBOARD_KPI_GLOSSARY_SLUGS = METRIC_GLOSSARY_INDEX_SLUGS
export const GLOSSARY_TOPIC_SECTIONS: {
id: string
label: string
- slugOrder: readonly DashboardKpiGlossarySlug[]
-}[] = GLOSSARY_TOPIC_SECTIONS_RAW.map((topic) => ({
+ slugOrder: readonly MetricGlossarySlug[]
+}[] = METRIC_GLOSSARY_TOPIC_SECTIONS_SOURCE.map((topic) => ({
id: topic.id,
label: topic.label,
slugOrder: topic.slugOrder,