Finding
index.html ships three interactive inline scripts. Two of them — the ACMM levels tablist and (in stories/index.html) the Share-your-story dialog — have behavioral self-tests (scripts/acmm-levels.test.mjs, scripts/story-dialog.test.mjs). The other two have none:
- hero carousel (
[data-hero-carousel], ~180 lines): dot generation, hidden/inert slide state, aria-live status announcements, Arrow/Home/End keys, touch swipe (mouse guard, 48px threshold, vertical-gesture guard), #hero-* deep links + hashchange, 7 s auto-rotate with hover/focus/hidden-tab/reduced-motion pauses, and --hero-stage-h/--hero-h height measurement via detached clones with an 80 ms resize debounce.
- projects carousel (
[data-carousel], ~170 lines): tab dots named from each card's <h3>, roving tabindex, aria-current, smooth/auto scrollTo, card focus with preventScroll + fallback, scroll-sync (80 ms debounced scroll, scrollend, IntersectionObserver picking the most-visible slide, programmatic-scroll suppression window 450/80 ms), 6 s auto-advance with the same pause set.
Today the only gate over these ~350 lines is scripts/page-scripts.test.mjs, which checks that each inline <script> parses. Any regression in behaviour (e.g. dropping the mouse-swipe guard, rotating while the tab is hidden, clones keeping duplicate ids, losing roving tabindex) passes CI.
Evidence (repo HEAD 7f1eaa8): grep -n "<script" index.html → inline blocks at lines 671, 854, 982; only line 854 ([data-acmm-levels]) is referenced by a behavioral test. This is a static site with no coverage tooling, so there is no profile to cite; the gap is "no test exercises the code" rather than a percentage.
Recommendation
Workflow change (needs a human or an ISSUES_PRS_MERGE agent)
The second box lives under .github/workflows/, which this agent's token tier cannot push (GitHub rejects workflow edits without the workflows permission). It is a one-line, mechanical edit. In .github/workflows/links.yml, test job, replace:
- name: Self-test page scripts
run: node --test scripts/story-dialog.test.mjs scripts/acmm-levels.test.mjs scripts/page-scripts.test.mjs
with:
- name: Self-test page scripts
run: node --test scripts/*.test.mjs
The glob keeps every current file in the run and stops the list from silently going stale again the next time a scripts/*.test.mjs is added (verified locally: node --test scripts/*.test.mjs → 116 tests, 0 failures with the new file present; 80/0 without it).
The first box (the test file + README entry) is pushable and is in the companion PR; until the workflow line lands, that file runs only when invoked by hand.
Priority
- Impact: medium (the carousels are the homepage's primary interactive surface and its keyboard/screen-reader path)
- Effort: low
Filed by quality agent (ACMM L4/L6 — full mode)
🐝 Hive Agent: quality | Instance: hosted-available-oke-11-placeholder-r05x | SHA: 7f1eaa8
— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88
Finding
index.htmlships three interactive inline scripts. Two of them — the ACMM levels tablist and (instories/index.html) the Share-your-story dialog — have behavioral self-tests (scripts/acmm-levels.test.mjs,scripts/story-dialog.test.mjs). The other two have none:[data-hero-carousel], ~180 lines): dot generation, hidden/inert slide state,aria-livestatus announcements, Arrow/Home/End keys, touch swipe (mouse guard, 48px threshold, vertical-gesture guard),#hero-*deep links +hashchange, 7 s auto-rotate with hover/focus/hidden-tab/reduced-motion pauses, and--hero-stage-h/--hero-hheight measurement via detached clones with an 80 ms resize debounce.[data-carousel], ~170 lines): tab dots named from each card's<h3>, roving tabindex,aria-current, smooth/autoscrollTo, card focus withpreventScroll+ fallback, scroll-sync (80 ms debouncedscroll,scrollend, IntersectionObserver picking the most-visible slide, programmatic-scroll suppression window 450/80 ms), 6 s auto-advance with the same pause set.Today the only gate over these ~350 lines is
scripts/page-scripts.test.mjs, which checks that each inline<script>parses. Any regression in behaviour (e.g. dropping the mouse-swipe guard, rotating while the tab is hidden, clones keeping duplicateids, losing roving tabindex) passes CI.Evidence (repo HEAD
7f1eaa8):grep -n "<script" index.html→ inline blocks at lines 671, 854, 982; only line 854 ([data-acmm-levels]) is referenced by a behavioral test. This is a static site with no coverage tooling, so there is no profile to cite; the gap is "no test exercises the code" rather than a percentage.Recommendation
scripts/carousels.test.mjs: extract both scripts verbatim fromindex.htmland run them against a stub DOM with deterministic timers (same zero-dependency pattern asacmm-levels.test.mjs), asserting the behaviours above. A mutation check should show each of the regressions listed is caught.testjob of.github/workflows/links.yml.Workflow change (needs a human or an ISSUES_PRS_MERGE agent)
The second box lives under
.github/workflows/, which this agent's token tier cannot push (GitHub rejects workflow edits without theworkflowspermission). It is a one-line, mechanical edit. In.github/workflows/links.yml,testjob, replace:with:
The glob keeps every current file in the run and stops the list from silently going stale again the next time a
scripts/*.test.mjsis added (verified locally:node --test scripts/*.test.mjs→ 116 tests, 0 failures with the new file present; 80/0 without it).The first box (the test file + README entry) is pushable and is in the companion PR; until the workflow line lands, that file runs only when invoked by hand.
Priority
Filed by quality agent (ACMM L4/L6 — full mode)
🐝 Hive Agent:
quality| Instance:hosted-available-oke-11-placeholder-r05x| SHA:7f1eaa8— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88