# 2026-07-17 — P1-11 vocab sweep + P1-UX-5b terminology hook Branch: `feat/p1-11-and-ux5b-shapeshift` Worktree: `.worktrees/feat-p1-11-and-ux5b-shapeshift` ## Why The UI/UX feedback PDF (§5 Global terminology, §6 Teacher Dashboard, §7 Notice Board, §8 Curriculum Portfolio, §9 Course Scheme/Plan) requires many user-facing labels to change. Hunting these down through 100+ components every time is unsustainable, so the work is in two halves: 1. A small `terminology.ts` dictionary + `useTerminology()` hook that every UI label can route through going forward. 2. Surgical text edits to the highest-traffic teacher/notice-board dashboards so the new language ships immediately on the Pilot UAT deploy. ## Changes ### `client/src/lib/terminology.ts` (new) Single source of truth for all replaced terms. Exports: - `T` — frozen flat dictionary (`STUDENT: 'Learner'`, `MATERIAL_ASSETS: 'Learning Material'`, `VIEW_ROSTER: 'View Learners'`, `ARCHIVE_COURSE: 'Delete'`, `GRADING: 'Marking'`, `THRESHOLD: 'Average'`, `MARKED: 'Excused'`, `OUTLIERS: 'Below Average'`, `STUDENT_DRILLDOWN: 'Learner Remedial Record'`, `BROADCAST: 'Notification'`, plus PDF §9 entries). - `T_TIERED` — dictionary keyed by `primary` / `secondary` / `tertiary` for entries that genuinely differ per tier. - `TIER` / `ACTIVE_TIER` — constants. `ACTIVE_TIER` is hard-coded `tertiary` for now; will read from `school_settings.school_tier` once that column lands. - `useTerminology()` — hook returning `{ tier, T, T_TIERED, term, label }`. `label('Course')` resolves to the current tier's mapping. ### `client/src/test/terminology.test.ts` (new, 15 specs) Vitest. Asserts every PDF § value is present and that `termFor` / `label` resolve tiered entries correctly. ### User-facing label edits (text-only, 6 files) | File | PDF § | Edits | |---|---|---| | `pages/teacher/TeacherDashboard.tsx` | §6 | `Students → Learners`, `Pending Grading → Pending Marking`, `Below Threshold → Below Average`, `Outliers (avg < 50%) → Below Average (avg < 50%)`, `Marked → Excused` (attendance callout), `Student Drill-down → Learner Remedial Record` | | `pages/teacher/MyCourses.tsx` | §8 | `Material Assets → Learning Material`, `View Roster → View Learners`, `Archive Course → Delete` | | `pages/Classes.tsx` | §9 | `Export Intel → Export Scheme` | | `pages/teacher/Extracurriculars.tsx` | §7 | `Broadcast update to members → Notification update to members`, `Broadcast Update → Notification Update` button | | `pages/teacher/Students.tsx` | §7 | `Broadcast Notice → Notification` button | No code identifiers, SQL columns, route paths, or variable names were touched. Identifier substitutions happen at the schema layer (separate follow-up, not user-blocking). ## Tier switching — a note `ACTIVE_TIER` is currently hard-coded `tertiary`. Wiring it to `school_settings.school_tier` (or a school-wide setting) is the next sprint. Until that lands, every tier-aware label uses the tertiary mappings. This matches the demo state and keeps the default-pilot-deployable promise. ## Verification - `npx vitest run` (client) → **45 / 45 passed** (5 spec files; 15 new from this PR). - Manual diff review: every edit is a literal string change; no logic changes, no API surface changes. ## Out of scope - Tier wiring (school_settings.school_tier). Tracked separately. - §8/§9 substitutions in pages that don't exist yet (Course Scheme/Plan, Curriculum Portfolio). Those land in P1-UX-7. - Identifier-level renames (variable names like `student_id` keep the schema's choice; no PR will rename `users.id`).