From c33365b5387abce7ab2af07a6886f7955b7ba065 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 07:30:12 +0000 Subject: [PATCH 1/2] chore: apply trivial consolidation fixes - Regenerate docs/test-coverage-report.md via `npm run analyze:e2e-gaps` (previous report dated 2025-11-26; now 15 spec files / 92 tests) - Remove stray temp-e2e/analysis-test.html left at repo root - Add a "superseded by spec 012" banner to CODE_REVIEW_REFACTORING_HOTSPOTS.md so readers know its file paths describe the pre-refactor codebase Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_015u1mfVebscuZA3YDc6hc87 --- CODE_REVIEW_REFACTORING_HOTSPOTS.md | 2 + docs/test-coverage-report.md | 79 ++++++++------- temp-e2e/analysis-test.html | 150 ---------------------------- 3 files changed, 43 insertions(+), 188 deletions(-) delete mode 100644 temp-e2e/analysis-test.html diff --git a/CODE_REVIEW_REFACTORING_HOTSPOTS.md b/CODE_REVIEW_REFACTORING_HOTSPOTS.md index 57f0a65a..2b33af1e 100644 --- a/CODE_REVIEW_REFACTORING_HOTSPOTS.md +++ b/CODE_REVIEW_REFACTORING_HOTSPOTS.md @@ -1,5 +1,7 @@ # Sonar Quiz System - Code Review: Refactoring Hotspots +> **Status (2026-09-05): superseded.** This review (Nov 2025) seeded [spec 012 — code review / hot-spot refactor](specs/012-code-review/), which was completed and merged in June 2026. The file paths, line counts and line numbers below describe the **pre-refactor** codebase and no longer match `src/` (for example `qd-instructor-login-modal.ts`, `quiz-inputs/`, `qd-student-answers-list.ts` do not exist). Kept for historical context only; see `docs/PROJECT_STATE.md` for the current state. + ## Executive Summary This code review identifies 18 high-priority refactoring opportunities across 791 total lines in the largest files. The primary issues are: diff --git a/docs/test-coverage-report.md b/docs/test-coverage-report.md index 761df9fa..9163fdec 100644 --- a/docs/test-coverage-report.md +++ b/docs/test-coverage-report.md @@ -1,14 +1,14 @@ # E2E Test Coverage Report -Generated: 2025-11-26 +Generated: 2026-09-05 ## Summary - **Total Features**: 11 - **Covered**: 11 (100%) - **Gaps**: 0 -- **E2E Spec Files**: 12 -- **Total Tests**: 82 +- **E2E Spec Files**: 15 +- **Total Tests**: 92 ## Feature Coverage Matrix @@ -16,68 +16,71 @@ Generated: 2025-11-26 |---------|---------------|--------| | Student login | analysis-capture.spec.ts | ✅ Covered | | Instructor login | analysis-capture.spec.ts | ✅ Covered | -| Quiz interaction (MCQ) | cohort-management.spec.ts | ✅ Covered | -| Quiz interaction (Numeric) | cohort-management.spec.ts | ✅ Covered | +| Quiz interaction (MCQ) | answer-styling-reset.spec.ts | ✅ Covered | +| Quiz interaction (Numeric) | answer-styling-reset.spec.ts | ✅ Covered | | Analysis table editing | analysis-capture.spec.ts | ✅ Covered | | Progress tracking (R/A/G badges) | dita-instructor-flow.spec.ts | ✅ Covered | | Session management (timeout) | session-timeout.spec.ts | ✅ Covered | | Data export (CSV) | csv-export.spec.ts | ✅ Covered | | Cohort management (data erasure) | cohort-management.spec.ts | ✅ Covered | | Build info display | build-info.spec.ts | ✅ Covered | -| PIN authentication | build-info.spec.ts | ✅ Covered | +| PIN authentication | answer-styling-reset.spec.ts | ✅ Covered | ## Spec File Analysis | Spec File | Tests | Clicks | Fills | Waits | Assertions | |-----------|-------|--------|-------|-------|------------| | analysis-capture.spec.ts | 7 | 10 | 13 | 0 | 18 | -| build-info.spec.ts | 9 | 2 | 3 | 0 | 13 | -| cohort-management.spec.ts | 4 | 27 | 22 | 0 | 50 | -| csv-export.spec.ts | 6 | 19 | 13 | 0 | 36 | +| answer-styling-reset.spec.ts | 2 | 2 | 3 | 1 | 4 | +| build-info.spec.ts | 9 | 1 | 3 | 0 | 13 | +| cohort-management.spec.ts | 4 | 26 | 22 | 0 | 50 | +| csv-export.spec.ts | 6 | 18 | 13 | 0 | 36 | | data-coexistence.spec.ts | 5 | 11 | 20 | 0 | 14 | -| dita-instructor-flow.spec.ts | 4 | 15 | 13 | 1 | 26 | -| dita-student-flow.spec.ts | 12 | 28 | 42 | 1 | 50 | -| instructor-mode-improvements.spec.ts | 8 | 17 | 5 | 0 | 21 | -| instructor-review.spec.ts | 5 | 19 | 8 | 0 | 34 | -| pin-authentication.spec.ts | 8 | 13 | 7 | 6 | 15 | -| progress-tracking.spec.ts | 7 | 9 | 22 | 0 | 16 | -| session-timeout.spec.ts | 7 | 14 | 22 | 0 | 20 | +| dita-instructor-flow.spec.ts | 4 | 14 | 13 | 1 | 25 | +| dita-student-flow.spec.ts | 12 | 27 | 42 | 1 | 50 | +| instructor-dynamic-reveal.spec.ts | 3 | 8 | 6 | 1 | 22 | +| instructor-mode-improvements.spec.ts | 8 | 16 | 5 | 0 | 21 | +| instructor-review.spec.ts | 5 | 18 | 8 | 0 | 34 | +| pin-authentication.spec.ts | 11 | 15 | 8 | 6 | 26 | +| progress-tracking.spec.ts | 7 | 8 | 22 | 0 | 16 | +| relogin-progress.spec.ts | 2 | 4 | 3 | 1 | 5 | +| session-timeout.spec.ts | 7 | 13 | 22 | 0 | 20 | ## Tested Selectors Top selectors by frequency: -- `qd-login` (12 specs) -- `input[name=` (12 specs) -- `button[type=` (12 specs) -- `qd-status` (12 specs) +- `qd-login` (15 specs) +- `input[name=` (15 specs) +- `button[type=` (15 specs) +- `qd-status` (15 specs) +- `table.qd-quiz` (12 specs) +- `.qd-quiz-input` (12 specs) +- `button` (10 specs) - `qd-login[data-ready]` (9 specs) -- `button` (9 specs) -- `table.qd-quiz` (9 specs) -- `.qd-quiz-input` (9 specs) -- `#qd-pin-confirmation-ok` (8 specs) -- `.qd-modal-backdrop input[type=` (7 specs) -- `.qd-modal-backdrop button[type=` (7 specs) +- `qd-modal[open] input[type=` (8 specs) +- `qd-modal[open] button[type=` (8 specs) - `View All Scores` (6 specs) -- `qd-login button` (5 specs) +- `qd-login button` (6 specs) - `td.interactive` (4 specs) -- `.qd-modal-backdrop` (4 specs) +- `.logout-button` (4 specs) +- `tbody tr` (4 specs) +- `td` (4 specs) +- `qd-modal[open]` (4 specs) - `table.qd-analysis` (3 specs) -- `.progress-text` (2 specs) -- `.logout-button` (2 specs) -- `qd-instructor` (2 specs) -- `input[type=` (2 specs) +- `.progress-text` (3 specs) +- `qd-instructor` (3 specs) ## Action Summary | Action | Count | |--------|-------| -| page.click() | 184 | -| page.fill() | 190 | -| page.waitForSelector() | 8 | -| page.check() | 2 | -| page.selectOption() | 29 | -| page.goto() | 101 | +| page.click() | 191 | +| page.fill() | 203 | +| page.waitForSelector() | 11 | +| page.check() | 3 | +| page.selectOption() | 34 | +| page.goto() | 110 | ## Gaps Requiring Attention diff --git a/temp-e2e/analysis-test.html b/temp-e2e/analysis-test.html deleted file mode 100644 index 7405ddec..00000000 --- a/temp-e2e/analysis-test.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - Analysis Capture E2E Test - - - -

Analysis Capture Test Page

-

This page is used for E2E testing of analysis table functionality.

- - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterValueNotes
Temperature
Pressure
Salinity
- - - - \ No newline at end of file From 328a2f5ecb2e9333e545166b17e17a48b0c07e83 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 07:30:12 +0000 Subject: [PATCH 2/2] docs: add project state consolidation report Audit of the dormant codebase ahead of a formal restart, written for an incoming maintainer. Covers: verification results from running every check locally (typecheck, lint, coverage, gaps, build, size, Storybook build, E2E in both storage modes), architecture drift against Technical_Design.md, a classification of every root/docs markdown file, test and visual-regression status, a maintainer-documentation gap assessment, and a risk-ranked restart backlog. Key findings recorded: Chromatic/Storybook build broken since the June refactor and masked by continue-on-error; coverage thresholds never evaluated in CI; E2E job disabled; "Erase All Data" clears sessionStorage only; 14 of 20 design-doc claims no longer hold. Also links the report from the Key Documentation list in CLAUDE.md. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_015u1mfVebscuZA3YDc6hc87 --- CLAUDE.md | 1 + docs/PROJECT_STATE.md | 249 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 docs/PROJECT_STATE.md diff --git a/CLAUDE.md b/CLAUDE.md index f05cf0cb..12fa7be3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -488,6 +488,7 @@ Enable via `data-qd-debug` attribute on quiz/analysis tables: ## Key Documentation +- **docs/PROJECT_STATE.md**: Consolidation audit (2026-09-05): verification results, design drift, doc audit, restart backlog - **System_Requirements.md**: Functional requirements, data model, authoring rules - **Technical_Design.md**: Architecture, packaging, integration patterns - **ARCHITECTURE_FLOWS.md**: Event flows, login processes, DOM patterns, service interactions diff --git a/docs/PROJECT_STATE.md b/docs/PROJECT_STATE.md new file mode 100644 index 00000000..15383b96 --- /dev/null +++ b/docs/PROJECT_STATE.md @@ -0,0 +1,249 @@ +# Project State — Consolidation Report (2026-09-05) + +Audit of the dormant BrowserTest ("Sonar Quiz System") codebase ahead of a formal restart. +Written for an incoming maintainer. Every number below comes from commands run on +2026-09-05 against `main` at `5383ca2` (last commit 2026-06-19), on Node 22.22 / npm 10.9. +Existing documents were audited, not rewritten. + +## 1. Summary + +- **The code is healthy; the project's picture of itself is not.** Type-check, lint, format, + build, size budget, 831 unit tests, 84 integration tests and 105 Playwright E2E tests all pass. + The documentation, CI signals and version stamps say otherwise or say nothing. +- **Chromatic visual regression has been silently broken since the June 2026 refactor.** + `storybook build` fails on an orphan story (`stories/components/qd-error-banner.stories.ts` + imports a component deleted in spec 012). CI shows green because the job has + `continue-on-error: true`. PR-preview Storybook deploys skip for the same reason. +- **Two quality gates are decorative.** The 80% coverage thresholds in `vitest.config.ts` are + never evaluated in CI (CI runs `test:unit`, not `test:coverage`), and would fail if they were + (62% unit lines, 40% integration lines). The E2E job in `ci.yml` is commented out. +- **"Erase All Data" does not erase IndexedDB.** It clears sessionStorage only; the adapter's + `clearAll()` has no callers. The E2E test documents this in a comment rather than failing. + This contradicts Constitution VI and the CLAUDE.md description of the button. +- **`Technical_Design.md` describes a system that was never built as written.** Of 20 checked + claims, 6 match, 8 have drifted and 6 are not implemented (Section 4). Event names, the + component model, `data-qd-*` flags, the public `init()` API and cross-tab sync are all wrong. +- **Two of the largest root docs are actively misleading** (they cite files deleted in June), + five `SECURITY_*.md` files (125 KB) overlap heavily, and README/CLAUDE.md link to two + documents that do not exist. There is no maintainer guide; `CLAUDE.md` is the de facto one. +- **Loose ends are few and specific:** spec 009 has three open tasks for an E2E file that was + never written; four modules (`validation.ts`, `csv-export.ts`, `runtime-config.ts`, + `qd-pin-create.ts`) are fully built but unwired; the toolbar unlock path reads a config span + the DITA template never emits. + +## 2. Repository snapshot + +| Item | Value | +|---|---| +| Last commit | `5383ca2` 2026-06-19, merge of PR #94 (spec 012 complete) | +| Working tree at audit start | clean; no WIP, no open PRs, no tags | +| `package.json` version | 0.2.0 | +| `src/index.ts` `VERSION` | `'0.1.0-phase3.1'` (stale; surfaced in ``) | +| Source | 91 files, ~14,840 LOC under `src/` | +| Tests | 52 unit, 12 integration, 16 E2E spec files (~20,400 LOC) | +| TODO/FIXME in `src/` | 0 | +| CI on `main` | green (lint, unit+integration, build+size); E2E disabled; Chromatic masked | +| Releases | `release.yml` triggers on `v*` tags; no tag has ever been pushed, so it is unexercised | + +Activity came in two bursts: Nov 2025 (all design/security docs, phases 0–7) and June 2026 +(specs 005–012, a large refactor). Only `CLAUDE.md` was updated during the second burst. + +## 3. Verification results + +| Command | Result | Headline | +|---|---|---| +| `npm run typecheck` | pass | | +| `npm run lint` | pass | 0 errors | +| `npm run format:check` | pass | | +| `npm run test:coverage:unit` | tests pass, **thresholds fail** | 52 files / 831 tests; lines 62.4%, branches 86.8%, functions 71.6% vs 80% | +| `npm run test:coverage:integration` | tests pass, **thresholds fail** | 12 files / 84 tests; lines 39.6%, branches 71.0%, functions 43.5% | +| `npm run test:gaps` | ran | 39 of 86 source files reported without a test (see caveat below) | +| `npm run build` | pass | IIFE 148 KB raw, ESM 239 KB raw | +| `npm run size-check` | pass | IIFE 37.61 KB gzipped, limit 40 KB (2.39 KB headroom) | +| `npm run build-storybook` | **fail** | `Could not resolve "../../src/components/qd-error-banner.js"` | +| `npm run test:e2e` | pass | 105 passed in 1.6 min (Storybook dev server started manually, see note) | +| `npm run test:e2e:encrypted` | pass | 104 passed, 1 skipped (Storybook started with `ENCRYPT_STORAGE=true`) | +| `npm run analyze:e2e-gaps` | ran | regenerated `docs/test-coverage-report.md` (was dated 2025-11-26) | +| Chromatic | not runnable locally | needs `CHROMATIC_PROJECT_TOKEN`; CI log inspected instead | + +Notes: +- Unit and integration coverage are separate runs with separate reports; there is no merged + figure. Per-directory unit line coverage: `services/auth` 98%, `utils` 82%, `components` 74%, + `config` 72%, `services` 71%, `enhancers` 17%, `init` 0%, `index.ts` 0%. Integration covers + `enhancers` 71% and `init` 60% but `components` 10%. Neither suite alone represents the code. +- `test:gaps` is structural and path-mirrored. 7 of its 39 "missing" files have a test at a + flat path it does not look for (e.g. `tests/unit/auth-service.test.ts`). Real gaps remain in + `src/init/` (all four modules), `src/services/storage/` (codec, connection, repositories), + `src/enhancers/` persistence modules and `src/services/state-calculator.ts`. +- `analyze:e2e-gaps` scans `tests/e2e/workflows/` only; `tests/e2e/help-popups.spec.ts` is + invisible to it. Its feature inventory is hard-coded, so "11/11 covered" is a floor, not proof. +- E2E: in this sandbox Playwright's `webServer` (`npm run storybook`) failed to spawn a browser + opener (`spawn none ENOENT`). Starting Storybook with `--ci --no-open` and letting Playwright + reuse it worked. Storybook **dev** mode tolerates the orphan story; **build** mode does not. + +## 4. Architecture drift vs `Technical_Design.md` + +The design doc (7 KB, last edited 2025-11-28) predates the PIN, help, migration, obfuscation, +audit-log and build-info features and the June 2026 refactor. Checked claim by claim: + +| § | Claim | Verdict | Evidence | +|---|---|---|---| +| 3 | Components are `` and ``; rest by DOM upgrade | Drifted | 23 custom elements registered under `src/components/` | +| 3 | `#qd-status` placeholder panel | Not implemented | Components appended into the `#qd-status-container` selector by `src/init/component-injector.ts`; `#qd-status` never queried | +| 3 | Zero or one `table.qd-quiz.qd-page` per page | Drifted | `.qd-page` appears nowhere; all `table.qd-quiz` matches are enhanced in a loop, no cardinality check (`src/init/bootstrap.ts`) | +| 7 | Page object fields; `qd/state` cache key; `qd/{release}/u{serviceId}` record key | Matches | `src/types/contracts.ts`, `src/services/storage/adapter-utils.ts` | +| 8 | Obfuscation is "future", keyed by `{release, serviceId}` | Drifted | Shipped behind build-time `ENCRYPT_STORAGE`; key derived from release only (`src/services/storage/obfuscation.ts`) | +| 11 | UI strings in an internal dictionary; `en-GB` dates | Not implemented / Drifted | Strings inline in Lit templates; `src/utils/date-helpers.ts` uses `en-US` | +| 12 | Author-error banner; storage-fault retry prompt | Not implemented | `src/services/validation.ts` (364 lines) has no importer; `qd:storage-error` is declared but never dispatched | +| 16 | `data-qd-debug` attribute enables debug | Not implemented | No `data-qd-debug` read; `setDebugMode()` in `src/utils/logger.ts` has no callers, so debug is permanently off. CLAUDE.md's "`DEBUG_MODE` constant in `src/index.ts`" does not exist either | +| 17 | Feature flags via `data-qd-*` attributes | Not implemented | Only flag is build-time `ENCRYPT_STORAGE`; `src/config/runtime-config.ts` defines a full runtime config with zero importers | +| 18 | CSV export prompt before erase | Not implemented | `qd-instructor-manage.ts` goes from typed confirmation straight to clear | +| 18 | Erase clears IndexedDB + sessionStorage | **Drifted (defect)** | `clearQuizData()` in `src/utils/storage-helpers.ts` iterates sessionStorage only; `StorageService.clearAll()` has no callers | +| 19 | Events dispatched on `window` | Drifted | All bus events dispatch on `document` (`src/utils/event-helpers.ts`) | +| 19 | Event names `qd:status-changed`, `qd:unlock`, `qd:lock`, `qd:analysis-cell-change`, `qd:show-all-responses`, `qd:erase`, `qd:error` | Drifted | Actual: `qd:state-changed`, `qd:instructor-unlock/-lock`, `qd:analysis-saved`, `qd:instructor-show-answers/-hide-answers`, `qd:data-cleared`; no error event. ~14 further events undocumented; `qd:analysis-saved`, `qd:cache-*`, `qd:badge-update`, `qd:pin-*` have no listeners | +| 19 | `window.SonarQuiz.init()` re-init API | Not implemented | Global is Rollup's IIFE namespace; export is `bootstrap()` (guarded, no re-init) plus `cleanup()` | +| 20 | Cross-tab broadcast | Not implemented | No `BroadcastChannel` or `storage` listener | +| 7 | 30-minute session timeout | Matches | `src/init/session-coordinator.ts`; expiry is silent (no event, no UI notice) | +| 5 | CI runs e2e and size check | Half true | size-check yes; E2E commented out | +| VIII | Answers removed from DOM on load | Matches, with a gap | `hideAnswerColumn()` blanks the answer cell; `hideDetailColumn()` only adds a CSS class, so the Detail column (MCQ `
    ` options, numeric tolerances) stays in the DOM; the leak is the tolerance value, since options are shown to students anyway (`src/enhancers/quiz-table-columns.ts`) | + +Undocumented in the design doc but present in code: PIN authentication (service, rate limiter, +three components), help popups, obfuscation migration dialog, audit-log and backup object stores +(DB version 3, three stores; CLAUDE.md says two), schema v1→v2 migration, scores modal, build-info +stamp, CSS answer hiding. + +Two further code-level findings a maintainer should know: +- **Duplicate instructor-hash config.** `src/services/auth/instructor-auth.ts` reads + `#qd-instructor-hash` (emitted by `dita/template/xslt/inc/customHeader.xsl`). + `src/config/instructor-password.ts` reads `#instructor.password.hash`, which the template never + emits; it is used only by the toolbar `` button, so that path always fails + in DITA output. Stories and unit tests provide the second id, which is why nothing catches it. +- **Dead modules:** `src/services/validation.ts`, `src/services/csv-export.ts`, + `src/config/runtime-config.ts`, `src/components/qd-pin-create.ts` have no importers. Their + presence inflates the untested-file count and the reader's mental model. + +`ARCHITECTURE_FLOWS.md` and `CLAUDE.md` are broadly consistent with the code at the level of +flows and file paths. CLAUDE.md is wrong on: `DEBUG_MODE` constant, object-store count, and +the erase-all description. It also says "Phase 1 Complete → Starting Phase 2", which is false. + +## 5. Documentation audit + +Status key: **Current** = safe to trust; **Historical** = accurate for its time, clearly dated; +**Stale** = will mislead; **Generated** = tool output. Disposition is a recommendation only. + +| File | KB | Last commit | Status | Reason | Suggested disposition | +|---|---|---|---|---|---| +| `CLAUDE.md` | 23 | 2026-06-17 | Current (minor errors) | Only doc updated in 2026; see §4 | Keep; fix the three errors; it is the maintainer guide until a real one exists | +| `README.md` | 6 | 2025-11-29 | Stale | "Status: In active development", "Phase 0 ← current", links `Delivery_Plan.md` and `Storybook_Plan.md` which do not exist | Rewrite the status/phase section; fix links | +| `Technical_Design.md` | 7 | 2025-11-28 | Stale | See §4: 14 of 20 claims wrong | Either re-baseline against code or mark "original design intent, not as-built" | +| `ARCHITECTURE_FLOWS.md` | 11 | 2025-11-18 | Current-ish | Flows still hold; event names partially outdated | Keep; update event names | +| `System_Requirements.md` | 8 | 2025-11-18 | Historical | Requirements baseline; predates PIN/help/encryption features | Keep as baseline; note additions from specs 003–010 | +| `Contracts.md` | 3 | 2025-11-18 | Current | Summary of `src/types/contracts.ts` | Keep | +| `CODE_REVIEW_REFACTORING_HOTSPOTS.md` | 22 | 2025-11-19 | Historical (banner added today) | Seeded spec 012; cites deleted files | Archive under `docs/history/` | +| `POST_PHASE_7_REVIEW.md` | 31 | 2025-11-18 | Stale | Cites `src/utils/attributes.ts`, `src/utils/events.ts` (gone); pre-refactor structure | Archive | +| `SECURITY_BEST_PRACTICES.md` | 54 | 2025-11-15 | Historical | Generic guidance from one commit; largest doc in repo | Merge the five SECURITY files into one project-specific page; archive the rest | +| `SECURITY_IMPLEMENTATION_GUIDE.md` | 19 | 2025-11-15 | Historical | Remediation plan, largely executed by spec 001 | Merge/archive | +| `SECURITY_TEST_EXAMPLES.md` | 30 | 2025-11-15 | Historical | Sample tests, some now real tests | Merge/archive | +| `SECURITY_README.md` | 12 | 2025-11-15 | Historical | Index for the above | Merge/archive | +| `SECURITY_QUICK_REFERENCE.md` | 10 | 2025-11-15 | Historical | Cheat-sheet | Merge/archive | +| `docs/COMPONENT_SPEC.md` | 14 | 2025-11-18 | Stale | Component list predates the qd-instructor split and PIN/help components | Re-baseline or archive | +| `docs/INSTRUCTOR_PASSWORD_IMPLEMENTATION.md` | 35 | 2025-11-18 | Historical | Design notes; does not mention the duplicate hash id | Archive | +| `docs/CODE_REDUCTION_PROPOSAL.md` | 3 | 2025-11-24 | Historical | Executed as spec 005 | Archive | +| `docs/RELEASE.md` | 3 | 2025-11-29 | Current (untested) | Process never exercised; no tags exist | Keep; exercise once | +| `docs/CHROMATIC_SETUP.md` | 2 | 2025-11-15 | Stale | Says "Chromatic is configured"; build is broken and token status unknown | Update after fix | +| `docs/test-coverage-report.md` | 2 | regenerated today | Generated | See §3 caveat on scope | Keep regenerating; do not hand-edit | + +Specs (`specs/`): 12 folders. 005–012 have spec/plan/tasks; all tasks closed except +**009-encrypt-stored-data** (T034, T035, T038 open: `tests/e2e/encrypted-storage.spec.ts` never +written). 000/001 predate the tasks convention. **003** and **004** have a spec and research but +no plan or tasks, yet their features (instructor improvements, PIN auth) are in the code, so +their implementation record is missing. Folder 002 does not exist. + +## 6. Test, coverage, E2E and visual-regression status + +**Unit (Vitest, jsdom, fake-indexeddb):** 831 tests, all green, ~20 s. Strong on +`services/auth`, `utils`, `components`; near-zero on `init/` and `enhancers/`. Console is noisy +with intentional `[ERROR]` logs from negative-path tests, which will hide a real error. + +**Integration (Vitest, separate config):** 84 tests, green. Covers `enhancers` and `init` +reasonably; almost nothing in `components`. + +**Coverage thresholds:** 80% on all four metrics in `vitest.config.ts`. Not evaluated in CI +(`ci.yml` runs `test:unit`/`test:integration`, uploads `coverage/lcov.info` to Codecov with +`if: always()`; the upload step succeeded on the last run but a Codecov token is not visible in +the workflow, so whether reports land is unknown). Both suites fail the thresholds locally. +Effective coverage gate: none. + +**E2E (Playwright, Chromium, against Storybook stories on :6006):** 105 tests, all green, +1.6 min. Per-test timeout is 2 s. Not run in CI ("temporarily disabled" comment in `ci.yml`, +job body still present). 4 tests in `pin-authentication.spec.ts` are `test.skip` unless +`ENCRYPT_STORAGE=true`. The encrypted variant requires Storybook to be started with the flag. +Run here with Storybook started under `ENCRYPT_STORAGE=true`: 104 passed, 1 skipped, 0 failed, +1.5 min. So both storage modes pass end-to-end today; neither is exercised in CI. + +**Visual regression (Chromatic):** configured in `ci.yml` (push to `main` only, +`continue-on-error: true`, `onlyChanged: true`) and in `.storybook/`. On the last `main` run +(2026-06-19, run 27829306417) the step reported success after 8 s; its log shows the Storybook +build failing on the orphan `qd-error-banner` story. So: no visual baseline has been captured +since before the June refactor, and whether `CHROMATIC_PROJECT_TOKEN` is even set cannot be +determined from the repo. `docs/CHROMATIC_SETUP.md` claims it works. + +**PR previews:** `pr-preview.yml` builds Storybook with a warn-and-skip on failure, so the +Storybook half of each PR preview has been silently absent since June. + +**Bundle:** 37.61 KB gzipped IIFE against a 40 KB budget, enforced in CI. 2.4 KB of headroom +is thin for a restart that adds features; the ESM build is 52.9 KB gzipped and unbudgeted. + +## 7. Maintainer-documentation gap + +What an incoming maintainer needs, and where it is today: + +| Need | State | Where | +|---|---|---| +| Purpose, constraints, constitution | Exists | `CLAUDE.md`, `System_Requirements.md` | +| Repo map (what lives where, what is dead) | Partial | `CLAUDE.md` layers section; dead modules and duplicate config not mentioned anywhere | +| Setup, build, test, lint commands | Exists | `CLAUDE.md` Development Commands; Definition of Done | +| How to run E2E locally, incl. Storybook quirks | Partial | `CLAUDE.md` says auto-managed; sandbox needed `--ci --no-open`; encrypted variant undocumented | +| Config contract (hidden spans, DITA XSL) | Exists, with a hole | `CLAUDE.md` Constitution VII; second hash id undocumented | +| Data model and storage layout | Partial | `Contracts.md`, `CLAUDE.md`; object-store count wrong; obfuscation key derivation only in code | +| Event catalogue | Wrong | `Technical_Design.md` §19 and `ARCHITECTURE_FLOWS.md` disagree with code; no single list | +| CI, deploy, PR preview, release | Exists | `CLAUDE.md` GitHub Pages section; `docs/RELEASE.md` (never exercised) | +| Chromatic / visual testing | Wrong | `docs/CHROMATIC_SETUP.md` | +| Known issues / deferred work | Missing | No list anywhere; this report is the first | +| Which documents to trust | Missing | 13 root docs, no index; this report's §5 is the first classification | +| Decision log (why Lit, why obfuscation not encryption, why PIN) | Partial | Scattered across `specs/*/research.md` and `plan.md`; not linked from anywhere | +| Authoring guide for DITA content authors | Partial | `CLAUDE.md` Author Constraints; the runtime validator that would enforce them is unwired | + +Verdict: the raw material for a maintainer guide exists, mostly in `CLAUDE.md` and `specs/`, +but it is written for an AI agent, has factual errors, and there is no known-issues list or +document index. A restart should produce a short `docs/MAINTAINERS.md` from this table rather +than another design document. + +## 8. Recommended restart backlog + +Ranked by risk. Effort: S (< half a day), M (1–2 days), L (more). + +| # | Item | Why it matters | Risk | Effort | +|---|---|---|---|---| +| 1 | Delete or rewrite `stories/components/qd-error-banner.stories.ts`; remove `continue-on-error` from the Chromatic job | Restores Storybook build, PR-preview Storybook and visual regression; ends a false-green signal | H | S | +| 2 | Decide what "Erase All Data" must do, then wire `StorageService.clearAll()` (or document the current behaviour and rename the button) | Constitution VI promises complete erasure; instructors will believe cohort data is gone when it is not | H | S–M | +| 3 | Re-enable the E2E job in `ci.yml` (body is already written; add `--ci` to the Storybook command) | 105 passing tests currently guard nothing on PRs | H | S | +| 4 | Make coverage a real gate or delete the thresholds: run `test:coverage:*` in CI with thresholds set to today's numbers, ratchet up | Thresholds that never run and would fail are worse than none | M | S | +| 5 | Resolve the duplicate instructor-hash id (`#instructor.password.hash` vs `#qd-instructor-hash`) to one reader | Toolbar unlock cannot work in DITA output; two code paths for one secret | M | S | +| 6 | Confirm `CHROMATIC_PROJECT_TOKEN` exists; capture a fresh baseline after #1 | Visual regression has had no baseline since before the refactor | M | S | +| 7 | Close spec 009: write `tests/e2e/encrypted-storage.spec.ts` or formally drop T034/T035/T038 | Only open tasks in the repo; encrypted mode is otherwise untested end-to-end in CI | M | M | +| 8 | Re-baseline `Technical_Design.md` against §4, or retitle it "original design intent" and point readers to an as-built doc | 14 of 20 claims wrong; a formal review will read it as truth | M | M | +| 9 | Remove or wire the dead modules (`validation.ts`, `csv-export.ts`, `runtime-config.ts`, `qd-pin-create.ts`) | 900+ lines that mislead readers and skew coverage; `validation.ts` is the only path to author-error banners | M | S–M | +| 10 | Fix `CLAUDE.md` errors (phase status, `DEBUG_MODE`, store count, erase-all) and add a Known Issues section | It is the document agents and people actually read | M | S | +| 11 | Fix README status/phase text and the two dead links; align `VERSION` in `src/index.ts` with `package.json` | First thing a reviewer sees | M | S | +| 12 | Archive `POST_PHASE_7_REVIEW.md`, `CODE_REVIEW_REFACTORING_HOTSPOTS.md`, `docs/CODE_REDUCTION_PROPOSAL.md`, `docs/INSTRUCTOR_PASSWORD_IMPLEMENTATION.md` under `docs/history/`; merge the five `SECURITY_*.md` into one | Halves the root doc set; removes files that cite deleted code | L | S | +| 13 | Strip the numeric tolerance from the Detail column in `quiz-table-columns.ts` as the answer column is, or accept that it is visible in view-source | Constitution VIII is only partly honoured; low impact (tolerance, not the answer) | L | S | +| 14 | Add unit tests for `src/init/*` and `src/services/state-calculator.ts`; make `test:gaps` path-aware or move the 7 flat tests, then run it `--strict` in CI | Bootstrap and state calculation are the two least-covered critical paths | M | M | +| 15 | Write `docs/MAINTAINERS.md` from §7 and a document index from §5 | No maintainer-facing entry point exists | M | S | +| 16 | Backfill plan/tasks for specs 003 and 004, or mark them "implemented without plan" | Two shipped features have no implementation record | L | S | +| 17 | Exercise the release workflow once with a `v0.2.0` tag | Release automation has never run | L | S | +| 18 | Budget the ESM bundle or state it is unbudgeted; note IIFE headroom is 2.4 KB | Any new feature will hit the limit | L | S | + +Trivial fixes applied in this consolidation PR: regenerated `docs/test-coverage-report.md`, +deleted the stray `temp-e2e/` folder, added a "superseded" banner to +`CODE_REVIEW_REFACTORING_HOTSPOTS.md`, and linked this report from `CLAUDE.md`.