|
| 1 | +# Theme Support MVP - validation plan, written before the work exists |
| 2 | + |
| 3 | +**Status: NOT RUN. This is a plan, not a record.** No validation has been |
| 4 | +performed. Nothing in this file is a result, an outcome or a finding about the |
| 5 | +theme feature, because on the date below the theme feature does not exist in any |
| 6 | +form that can be validated. |
| 7 | + |
| 8 | +Ticket: THM-MVP01. Objective: Light, Dark, and System Theme Support. |
| 9 | +Written: 27 August 2026. Validation cannot start before the objective does. |
| 10 | + |
| 11 | +## What this file is, and what it is not |
| 12 | + |
| 13 | +It **is** the instrument the final validation will be run from. It fixes the |
| 14 | +dependency register, the exact commands, the manual check matrix, the route |
| 15 | +matrix, the evidence rules, the handover skeleton and the sign-off list ahead of |
| 16 | +time, so the checklist cannot be quietly written to fit whatever happens to land. |
| 17 | + |
| 18 | +It is **not** evidence that any of that was done. Every cell that would hold a |
| 19 | +result says `NOT RUN`, and every table that would hold rows carries a single |
| 20 | +placeholder row instead. Those are deliberate, not an oversight. Filling one in |
| 21 | +before the run is the exact failure this ticket exists to prevent. |
| 22 | + |
| 23 | +If you are reading this looking for the outcome of the theme MVP validation, it |
| 24 | +is not here yet. Come back when the status line at the top has changed. |
| 25 | + |
| 26 | +## Dependency register, read 27 August 2026 |
| 27 | + |
| 28 | +**As of 27 August 2026 every ticket in this objective is Not started, including |
| 29 | +THM-MVP01 itself.** The objective holds seventeen THM tickets. Sixteen of them are |
| 30 | +dependencies and are listed below, alongside the two migration tickets the |
| 31 | +checklist also needs. Nothing has been built, so there is nothing to validate. |
| 32 | + |
| 33 | +Nothing here is overdue. The earliest due date in the table is 9 September 2026 |
| 34 | +and this plan was written on 27 August 2026, so Not started is the expected state |
| 35 | +for all of them. The table records the position on one named date. It is not a |
| 36 | +progress judgement on anybody. |
| 37 | + |
| 38 | +| Depends on | Owner | Due | Status, 27 Aug 2026 | |
| 39 | +|---|---|---|---| |
| 40 | +| THM-JL01 objective, approved branch path, ownership, MVP boundaries | Sanjana Bottu | 2026-09-20 | Not started | |
| 41 | +| THM-D01 audit and dark-mode blocker map | Owen Costin | 2026-09-20 | Not started | |
| 42 | +| THM-D02 theme contract and semantic design tokens | Samridh Limbu | 2026-09-09 | Not started | |
| 43 | +| THM-F01 theme foundation, System detection, persistence, no-flash startup | Maple 'Ryan' Fox | 2026-09-13 | Not started | |
| 44 | +| THM-F02 accessible Light, Dark, System preference control | Gaurav Myana | 2026-09-20 | Not started | |
| 45 | +| THM-F03 Tailwind dark variant on the approved root marker | unassigned | 2026-09-13 | Not started | |
| 46 | +| THM-F04 no-flash startup mechanism | unassigned | 2026-09-13 | Not started | |
| 47 | +| THM-B01 persist the preference on the user account | unassigned | 2026-09-16 | Not started | |
| 48 | +| THM-M01 application shell and shared components | Duong Bao Huy Tran | 2026-09-16 | Not started | |
| 49 | +| THM-M02 core student workflows | Swyam Khare | 2026-09-18 | Not started | |
| 50 | +| THM-M03 tutor, unit chair and administration workflows | Gaurav Myana | 2026-09-18 | Not started | |
| 51 | +| THM-M04 charts, calendars, editors, viewers, print, offline | Leeon Gourav Rangey | 2026-09-18 | Not started | |
| 52 | +| THM-M05 sequence the migration against the FlexLayout teardown | unassigned | 2026-09-09 | Not started | |
| 53 | +| THM-W01 installed-app splash and address-bar colours for dark | unassigned | 2026-09-18 | Not started | |
| 54 | +| THM-T01 automated theme tests and visual regression matrix | David Tenni | 2026-09-16 | Not started | |
| 55 | +| THM-Q01 independent accessibility, cross-browser, responsive, usability pass | Nephat Komu Muriithi | 2026-09-20 | Not started | |
| 56 | +| MG-04 catalogue of components on the old design language | unassigned | 2026-09-14 | Not started | |
| 57 | +| MG-05 CSS style guide | unassigned | 2026-09-14 | Not started | |
| 58 | + |
| 59 | +Seven of the eighteen have nobody on them. MG-04 and MG-05 in particular block |
| 60 | +checklist item 2, which cannot be answered at all until they have an owner. |
| 61 | + |
| 62 | +### Evidence for "Not started", repeatable in about a minute |
| 63 | + |
| 64 | +The board is one source. Git is the other, and it is the one a reviewer can check |
| 65 | +without a Planner login. Both agree. |
| 66 | + |
| 67 | +```bash |
| 68 | +export PAGER=cat GH_PAGER=cat GIT_PAGER=cat |
| 69 | + |
| 70 | +# 1. No theme branch on any repo in the org. 0 of 160 heads matched, |
| 71 | +# re-read 27 August 2026 after the MVP closure merge landed on 11.0.x. |
| 72 | +for r in doubtfire-web doubtfire-api doubtfire-deploy github-guide; do |
| 73 | + echo -n "$r: " |
| 74 | + git ls-remote --heads "https://github.com/ontrack-features-t2-2026/$r.git" \ |
| 75 | + | grep -Eic 'theme|thm|dark' |
| 76 | +done |
| 77 | + |
| 78 | +# 2. No theme pull request, in any state. 0 of 210 pull requests matched, |
| 79 | +# re-read the same day. |
| 80 | +for r in doubtfire-web doubtfire-api doubtfire-deploy; do |
| 81 | + echo -n "$r: " |
| 82 | + gh pr list --repo "ontrack-features-t2-2026/$r" --state all --limit 2000 \ |
| 83 | + --json number,title,headRefName \ |
| 84 | + --jq '[.[] | select((.title|test("(?i)theme|THM-")) or (.headRefName|test("(?i)theme|THM-")))] | length' |
| 85 | +done |
| 86 | + |
| 87 | +# 3. The theme contract THM-D02 defines is on no branch of origin. Check every |
| 88 | +# head, not just 11.0.x, or this only proves it is missing from one branch. |
| 89 | +git fetch origin --prune |
| 90 | +git ls-remote --heads origin | while read -r sha ref; do |
| 91 | + git cat-file -e "$sha:docs/theme/THEME-CONTRACT.md" 2>/dev/null \ |
| 92 | + && echo "contract present on ${ref#refs/heads/}" |
| 93 | +done |
| 94 | +echo "no line above means the contract is absent from every branch on origin" |
| 95 | +``` |
| 96 | + |
| 97 | +Results on 27 August 2026: every count in steps 1 and 2 returned `0`, and step 3 |
| 98 | +printed no branch line, across all 81 heads on `doubtfire-web`. Pass `--limit |
| 99 | +2000`. The default truncates silently and has already produced a wrong answer of |
| 100 | +zero for a different question. |
| 101 | + |
| 102 | +### THM-D02 is a dependency this plan cannot resolve yet |
| 103 | + |
| 104 | +Three things in this plan point at THM-D02: the DOM marker, the browser storage |
| 105 | +key and the validated theme enum. **All three are unresolved references.** THM-D02 |
| 106 | +is Not started, and `docs/theme/THEME-CONTRACT.md` is absent from every branch on |
| 107 | +`origin`, verified by step 3 above. A draft of that contract is committed on a |
| 108 | +local branch that has never been pushed, so it is not on `origin` and nobody else |
| 109 | +on the team can read it. It has not been reviewed and it has not landed, so it is |
| 110 | +not a source this plan may quote. |
| 111 | + |
| 112 | +This plan therefore names those three things by role and never by value. Do not |
| 113 | +substitute a guess. Every place below marked **depends on THM-D02** stays |
| 114 | +unresolved until that document is merged, and the first job of whoever runs this |
| 115 | +validation is to replace the role with the approved name and record where it came |
| 116 | +from. |
| 117 | + |
| 118 | +## Scheduling clash, for the objective lead |
| 119 | + |
| 120 | +THM-MVP01 is due **20 September 2026**. Four of the tickets it must validate, |
| 121 | +THM-JL01, THM-D01, THM-F02 and THM-Q01, are due on that same day. A validation |
| 122 | +ticket cannot fall due at the same moment as the work it validates, so one of the |
| 123 | +two dates has to move. Either THM-MVP01 moves later than 20 September, or those |
| 124 | +four move earlier. |
| 125 | + |
| 126 | +That is a sequencing decision for the objective lead and it is the first thing to |
| 127 | +raise. It is written down here rather than left in a chat so it does not get lost. |
| 128 | + |
| 129 | +## What can be started now, and what cannot |
| 130 | + |
| 131 | +| Checklist item | Can start now | Why | |
| 132 | +|---|---|---| |
| 133 | +| 1. Confirm each child ticket, PR, owner, final status | Partly | The register above exists. No PR and no final status does. | |
| 134 | +| 2. Confirm MG-04, MG-05 preserved and linked, THM-D03 not a duplicate | Partly | MG-04 and MG-05 are unassigned. No THM-D03 exists on the board, which is itself the finding. | |
| 135 | +| 3. Confirm the integration branch is based on latest approved 11.0.x | No | THM-JL01 has not named a branch, and no theme branch exists. | |
| 136 | +| 4. Review the complete diff | No | No diff exists. | |
| 137 | +| 5. Final targeted tests, full tests, typecheck, lint, production build | No | The commands are fixed below and can be rehearsed against `11.0.x` now for a baseline. | |
| 138 | +| 6. Light, Dark, System, reload, direct-route, live-change, no-flash checks | No | The feature does not exist. The check script below is written. | |
| 139 | +| 7. Review THM-Q01 blockers | No | THM-Q01 has not run. | |
| 140 | +| 8. Student, tutor, unit chair, admin route matrices | Partly | The route list can be enumerated from the router now. | |
| 141 | +| 9. Charts, calendar, editors, viewers, print, offline, browsers | Partly | The surface list can be enumerated from the repo now. | |
| 142 | +| 10. Evidence index | Yes | Template below. | |
| 143 | +| 11. Contributor attribution, completed vs deferred vs future | Yes | Structure below. | |
| 144 | +| 12. Handover, demo, rollback notes, next priorities | Yes | Skeleton below. | |
| 145 | +| 13. Lead approval and final PR into 11.0.x | No | Nothing to open a pull request for. | |
| 146 | + |
| 147 | +## Commands the final validation will run |
| 148 | + |
| 149 | +None of these have been run against a theme branch, because there is no theme |
| 150 | +branch. Run every one from the theme integration branch once THM-JL01 has named |
| 151 | +it. Record the exact output in the evidence index, not a summary of it. |
| 152 | + |
| 153 | +```bash |
| 154 | +# 1. Confirm the branch point. This must be an ancestor check, not a guess. |
| 155 | +git fetch origin |
| 156 | +git merge-base --is-ancestor origin/11.0.x origin/<theme-integration-branch> \ |
| 157 | + && echo "based on latest 11.0.x" || echo "BEHIND - rebase before validating" |
| 158 | +git rev-list --left-right --count origin/11.0.x...origin/<theme-integration-branch> |
| 159 | + |
| 160 | +# 2. The complete diff, for the unrelated-change review in item 4. |
| 161 | +git diff --stat origin/11.0.x...origin/<theme-integration-branch> |
| 162 | +git diff origin/11.0.x...origin/<theme-integration-branch> -- ':!*.scss' ':!*.css' |
| 163 | + |
| 164 | +# 3. Automated checks. All four scripts exist in package.json on 11.0.x. |
| 165 | +npm run lint # ng lint --max-warnings 0 |
| 166 | +npm run typecheck # ngc -p src/tsconfig.app.json --noEmit |
| 167 | +npm run test:ci # ng test --no-watch --no-progress (vitest) |
| 168 | +npm run build # ng build |
| 169 | + |
| 170 | +# 4. Record the exact SHAs that were validated. |
| 171 | +git rev-parse origin/<theme-integration-branch> origin/11.0.x |
| 172 | +``` |
| 173 | + |
| 174 | +Branch names come from `git ls-remote --heads origin`, never from `git branch -a`. |
| 175 | +On a case-insensitive filesystem the local ref list reports capitalised branches |
| 176 | +that do not exist on the server, because an inherited `Feature/` directory folds |
| 177 | +later lowercase refs into it. |
| 178 | + |
| 179 | +## Result tables, all empty by design |
| 180 | + |
| 181 | +**Everything from here to the approvals list is a blank instrument.** Every result |
| 182 | +cell says `NOT RUN` and every list carries one placeholder row. That is the |
| 183 | +intended state of this document until the objective ships. A cell filled in before |
| 184 | +its run is a fabricated result, and the point of writing these tables now is that |
| 185 | +nobody has to invent one later. |
| 186 | + |
| 187 | +Replace `NOT RUN` with PASS, FAIL or a specific finding only after watching the |
| 188 | +check happen. If a check could not be attempted, leave it `NOT RUN` and say why. |
| 189 | + |
| 190 | +### Manual check script |
| 191 | + |
| 192 | +Every row is repeated in Light, Dark and System. "System" means the operating |
| 193 | +system setting is changed while OnTrack stays open, not a reload. |
| 194 | + |
| 195 | +| # | Check | Light | Dark | System | |
| 196 | +|---|---|---|---|---| |
| 197 | +| 1 | First load with no stored preference falls back safely | NOT RUN | NOT RUN | NOT RUN | |
| 198 | +| 2 | First load with an invalid stored value falls back safely | NOT RUN | NOT RUN | NOT RUN | |
| 199 | +| 3 | No flash of the wrong theme on cold load | NOT RUN | NOT RUN | NOT RUN | |
| 200 | +| 4 | Reload preserves the chosen preference | NOT RUN | NOT RUN | NOT RUN | |
| 201 | +| 5 | Direct route to a deep URL renders in the right theme | NOT RUN | NOT RUN | NOT RUN | |
| 202 | +| 6 | OS preference changed while open, System follows it live | NOT RUN | NOT RUN | NOT RUN | |
| 203 | +| 7 | OS preference changed while open, explicit Light or Dark does not follow | NOT RUN | NOT RUN | NOT RUN | |
| 204 | +| 8 | Browser and installed-app chrome colour matches the resolved theme | NOT RUN | NOT RUN | NOT RUN | |
| 205 | +| 9 | Print output is readable | NOT RUN | NOT RUN | NOT RUN | |
| 206 | +| 10 | Offline service worker load renders in the right theme | NOT RUN | NOT RUN | NOT RUN | |
| 207 | + |
| 208 | +Rows 1, 2 and 4 read and write the browser storage key. Row 2 needs the validated |
| 209 | +theme enum to know what an invalid value even is. Both **depend on THM-D02** and |
| 210 | +cannot be written as concrete steps until that contract lands. |
| 211 | + |
| 212 | +### Route matrix |
| 213 | + |
| 214 | +One pass per role. Fill the route list from the router before the first validation |
| 215 | +run rather than from memory. |
| 216 | + |
| 217 | +| Role | Routes covered | Unreadable or broken | Result | |
| 218 | +|---|---|---|---| |
| 219 | +| Student | NOT RUN | NOT RUN | NOT RUN | |
| 220 | +| Tutor | NOT RUN | NOT RUN | NOT RUN | |
| 221 | +| Unit chair | NOT RUN | NOT RUN | NOT RUN | |
| 222 | +| Administrator | NOT RUN | NOT RUN | NOT RUN | |
| 223 | + |
| 224 | +Surfaces that historically resist theming, each needing a named result or an |
| 225 | +approved limitation: charts, calendar, the task editor, the PDF and portfolio |
| 226 | +viewers, code blocks, overlays and dialogs, print, offline. |
| 227 | + |
| 228 | +### Evidence index |
| 229 | + |
| 230 | +One row per artefact. A claim in the handover with no row here is a claim the |
| 231 | +maintainer cannot check. |
| 232 | + |
| 233 | +| # | Claim | Artefact | Location | Owner | Date | |
| 234 | +|---|---|---|---|---|---| |
| 235 | +| - | *no rows yet, the validation has not run* | - | - | - | - | |
| 236 | + |
| 237 | +Required artefact types: the final integration pull request, the exact final SHAs, |
| 238 | +the output of each command above, the manual check table filled in, screenshots or |
| 239 | +a short recording per theme state, the THM-Q01 report with every blocker marked |
| 240 | +fixed and retested, and the reviewer names against each approval. |
| 241 | + |
| 242 | +Sanitise every screenshot and recording before it goes in the pack. Use |
| 243 | +demonstration data, never real student submissions or real names. |
| 244 | + |
| 245 | +### Contributor attribution |
| 246 | + |
| 247 | +| Ticket | Contributor | What landed | PR | |
| 248 | +|---|---|---|---| |
| 249 | +| - | *no rows yet, nothing has landed* | - | - | |
| 250 | + |
| 251 | +Keep completed, deferred and future work in three separate lists. Do not fold a |
| 252 | +deferred item into the completed list because it was nearly done. |
| 253 | + |
| 254 | +| Accepted limitation | Reason | Owner | Next action | |
| 255 | +|---|---|---|---| |
| 256 | +| - | *no rows yet* | - | - | |
| 257 | + |
| 258 | +## Handover skeleton |
| 259 | + |
| 260 | +Two documents, both short. Neither has been written. |
| 261 | + |
| 262 | +**User guide.** What the three settings do, where the control is, what System |
| 263 | +means, and what happens if the operating system changes while OnTrack is open. |
| 264 | + |
| 265 | +**Technical handover.** The DOM marker and the storage key (**depends on THM-D02**, |
| 266 | +which is Not started and not on origin, so both are unresolved names today), where |
| 267 | +the semantic tokens live, how Tailwind and the shared SCSS consume them, which |
| 268 | +pages were migrated and which were not, how to add a token, how to theme a new |
| 269 | +component, and how to run the tests and the visual regression pass. |
| 270 | + |
| 271 | +**Rollback.** The exact revert path, what the application looks like with the |
| 272 | +feature off, and whether any stored preference has to be cleared. |
| 273 | + |
| 274 | +**Next priorities.** Ranked, with the reason each one is next. |
| 275 | + |
| 276 | +## Security and privacy sign-off |
| 277 | + |
| 278 | +None of these have been confirmed. Confirm before the final pull request and |
| 279 | +record who confirmed each line. |
| 280 | + |
| 281 | +| Line to confirm | Confirmed by | Date | |
| 282 | +|---|---|---| |
| 283 | +| The feature stores only the validated theme enum (**depends on THM-D02**) | NOT RUN | NOT RUN | |
| 284 | +| No assessment data, permission or authorisation behaviour changed | NOT RUN | NOT RUN | |
| 285 | +| The stored preference is never evaluated as CSS or as code | NOT RUN | NOT RUN | |
| 286 | +| Screenshots and recordings in the evidence pack are sanitised | NOT RUN | NOT RUN | |
| 287 | + |
| 288 | +## Approvals |
| 289 | + |
| 290 | +Left unticked, and they stay unticked. An approval belongs to the approver, not to |
| 291 | +the author of this file. |
| 292 | + |
| 293 | +- [ ] Objective lead, THM-JL01 |
| 294 | +- [ ] Frontend reviewer |
| 295 | +- [ ] Accessibility reviewer |
| 296 | +- [ ] Maintainer, for the final pull request into 11.0.x |
0 commit comments