mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-07-03 10:31:44 +00:00
d437958474df87556b429e6a2e691c7bca741512
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
735d9eb516 |
fix(#1715): dark-theme role swatches via per-theme CSS tokens (#1757)
## Summary Dark-theme variants of the neighbor-graph role swatches (`#ngRoleChecks` labels on `/analytics?tab=neighbor-graph`) still failed WCAG AA after #1720's light-theme fix because the swatches used inline `style="color:#..."` from `customize.js` `DEFAULTS.nodeColors` (palette-700) — bypassing the theme tokens entirely. Measured before: | Role | Color | vs `#1a1a2e` (dark) | |---|---|---| | repeater | `#dc2626` | 3.53:1 ❌ | | companion | `#2563eb` | 3.30:1 ❌ | | observer | `#8b5cf6` | 4.02:1 ❌ | ## Fix - Defines `--role-{repeater,companion,room,sensor,observer}` in `:root` (palette-700, ≥4.5:1 on white) and overrides them in both dark blocks (`[data-theme="dark"]` + the `@media (prefers-color-scheme: dark)` mirror) with palette-400/500 shades that clear AA on `#1a1a2e`. - Refactors the neighbor-graph swatch DOM in `public/analytics.js` from inline `style="color:${hex}"` to class-based `<span class="role-swatch role-swatch--{role}">`, with matching CSS rules that read the tokens. - Removes all 5 `#1715` entries from `tests/a11y-allowlist.yaml` per the issue's acceptance criteria. After: | Role | Light (vs `#fff`) | Dark (vs `#1a1a2e`) | |---|---|---| | repeater | `#dc2626` 4.83:1 | `#ef4444` 4.53:1 | | companion | `#2563eb` 5.17:1 | `#3b82f6` 4.64:1 | | room | `#15803d` 5.02:1 | `#16a34a` 5.18:1 | | sensor | `#b45309` 5.02:1 | `#d97706` 5.35:1 | | observer | `#7c3aed` 5.70:1 | `#a78bfa` 6.27:1 | ## Tests - `test-a11y-1715-dark-role-swatches.js` — CSS-driven WCAG AA probes for the 5 per-theme `--role-*` tokens plus markup invariants (no inline color span; class names present in `#ngRoleChecks` block). - Red commit: `a09ec21c` — fails on assertion with 12 below-threshold/markup probes. - Green commit: `f87dcd64` — all probes PASS. - `tests/a11y-allowlist.yaml` shed all 5 entries; the umbrella `test-a11y-axe-1668.js` (CI) is now the live-browser net for those cells. ## Preflight overrides - `check-xss-sinks.sh` flags `public/analytics.js:2502` (label "observer" appears in an `innerHTML=\`tpl\`` line). The flagged token is a hardcoded literal string — no user-controlled data flows into that template. No template content changed in this PR; the flag is preexisting noise from the heuristic scan and the gate ultimately marks ✅ pass. Fixes #1715 --------- Co-authored-by: clawbot <clawbot@kpa.local> Co-authored-by: clawbot <bot@example.com> |
||
|
|
0765c2cc69 |
fix(#1718): drop prefix-tool a11y allowlist entries — subsumed by #1720 (#1736)
## Summary PR #1720 (merged 2026-06-13) consolidated active button states onto the shared `.btn-active-accent` rule that paints `background: var(--accent-strong)` (`#2563eb`) + `color: var(--text-on-accent)` (`#f9fafb`) = **4.95:1**, WCAG AA pass in both themes. That subsumes the `#ptCheckBtn` / `#ptGenBtn` color-contrast violations issue #1718 tracked, so the allowlist entries are stale. ## Change Drop the two `issue: 1718` entries from `tests/a11y-allowlist.yaml`: ```yaml - route: '/analytics?tab=prefix-tool' selector: '#ptCheckBtn' rule: color-contrast issue: 1718 expires_at: 2026-09-11 - route: '/analytics?tab=prefix-tool' selector: '#ptGenBtn' rule: color-contrast issue: 1718 expires_at: 2026-09-11 ``` No other tabs touched. `#1715` dark-theme work and other `expires_at: 2026-09-11` entries are out of scope — separate issues, separate PRs. No production CSS/JS modified (PR #1720 did the substantive fix). ## Verification The CI a11y gate (`test-a11y-axe-1668.js`) is the authoritative check. It re-renders `/analytics?tab=prefix-tool` in dark+light × desktop+ mobile and asserts zero net violations against the trimmed allowlist. With this PR the entries are gone — if PR #1720's fix were ever reverted, the gate fails immediately with no allowlist masking it. Local repro not attempted: sandbox chromium lacks the `@axe-core/playwright` module (matches the documented limitation in PR #1730 / PR #1723). CI is the source of truth for this gate. ## TDD note Config-change exemption per workspace AGENTS.md: - No test files modified. - No production code modified. - Config-only allowlist trim; CI must stay green without test edits. - The gate itself is the test — dropping the allowlist entries IS the red→green transition (entries gone → axe runs unfiltered → must remain pass because #1720 fixed the root cause). Mirrors the exact pattern accepted in PR #1722 (clock-health), PR #1723 (subpaths), PR #1730 (nodes), and PR #1731 (rf-health) — same allowlist-drop shape, same upstream PR #1720 fix. ## Preflight `bash ~/.openclaw/skills/pr-preflight/scripts/run-all.sh origin/master` — config-only change; PII grep on diff clean. Fixes #1718. Refs PR #1720, PR #1722, PR #1723, PR #1730, PR #1731. Co-authored-by: Kpa-clawbot <bot@openclaw.local> Co-authored-by: efiten <erwin.fiten@gmail.com> |
||
|
|
1476b857d9 |
fix(#1716): drop rf-health a11y allowlist entry — subsumed by #1720 (#1731)
Fixes #1716. PR #1720 (merged 2026-06-13) consolidated `.rf-range-btn.active` — along with `.clock-filter-btn.active`, `.subpath-jump-nav a`, `.node-filter-option.node-filter-active`, `.subpath-selected`, and `.analytics-time-range button.active` — into the shared `.btn-active-accent` rule that paints `background: var(--accent-strong)` (`#2563eb`) + `color: var(--text-on-accent)` (`#f9fafb`) = **4.95:1**, WCAG AA pass in both themes. That makes the `#1716` axe allowlist entry obsolete: the underlying violation no longer reproduces. This PR drops the entry and adds a dedicated per-issue regression gate so a future refactor that only breaks `.rf-range-btn.active` (without touching the other consolidated selectors covered by `#1719`) trips with a clear `#1716` citation. ## Strict TDD red→green ### RED — `bce51a60` (test-only) Adds `test-a11y-1716-rf-range-btn-active.js`, a pure-CSS probe with three assertions: - **A1** — `.rf-range-btn.active` is routed through a rule whose body sets `background: var(--accent-strong)` + `color: var(--text-on-accent)`. - **A2** — the legacy `var(--accent)` + `#fff` pair (2.75:1) does NOT reappear on any block listing `.rf-range-btn.active`. - **A3** — numeric contrast on the resolved tokens is ≥ 4.5:1 in both light and dark themes. Locally verified the test FAILS when the consolidated active-button block is reverted to `background: var(--accent); color: #fff`: ``` PASS A3[light]: 4.95:1 (fg=#f9fafb bg=#2563eb) PASS A3[dark]: 4.95:1 (fg=#f9fafb bg=#2563eb) FAIL A1: .rf-range-btn.active is NOT routed through the consolidated (--accent-strong / --text-on-accent) pair — PR #1720 regression FAIL A2: legacy 2.75:1 pair re-emerged on .rf-range-btn.active (bg=var(--accent) fg=#fff) FAIL: 2 assertion(s) tripped on .rf-range-btn.active (issue #1716) ``` Then restored CSS — test passes green on the consolidated state from master. ### GREEN — `eea79791` Removes from `tests/a11y-allowlist.yaml`: ```yaml - route: '/analytics?tab=rf-health' selector: 'button[data-range="24h"]' rule: color-contrast issue: 1716 expires_at: 2026-09-11 ``` ### CI wiring — `b300ce6d` Hooks the new probe into the same `.github/workflows/deploy.yml` step that already runs `test-a11y-axe-1668-selftest.js` and `test-issue-1705-subpath-contrast.js`, so the gate runs on every PR. ## Gate output (after green) ``` $ node test-a11y-1716-rf-range-btn-active.js PASS A1: .rf-range-btn.active routes to var(--accent-strong) + var(--text-on-accent) PASS A2: no legacy var(--accent) + #fff pair on .rf-range-btn.active PASS A3[light]: 4.95:1 (fg=#f9fafb bg=#2563eb) PASS A3[dark]: 4.95:1 (fg=#f9fafb bg=#2563eb) PASS: .rf-range-btn.active gated by consolidated --accent-strong / --text-on-accent pair (issue #1716) ``` The umbrella `#1719` probe also still passes (`PASS: all 4 root-cause patterns ≥ 4.5:1 in both themes`). ## Scope Only the `rf-health` / `.rf-range-btn.active` line. The sibling allowlist entries for `#1714` (nodes), `#1715` (neighbor-graph), and `#1718` (prefix-tool) are out of scope — separate issues, separate PRs. No production CSS touched (PR #1720 did the substantive fix). ## Files changed - `tests/a11y-allowlist.yaml` (−5 lines: drop `#1716` entry) - `test-a11y-1716-rf-range-btn-active.js` (+177 lines: new regression gate) - `.github/workflows/deploy.yml` (+1 line: wire the new gate) ## Preflight All hard gates clean (PII, branch scope, red commit, CSS-var defined, CSS self-fallback, LIKE-on-JSON, sync migration, async migration, XSS sinks). All warnings clean. --------- Co-authored-by: openclaw-bot <bot@openclaw.local> |
||
|
|
b695aec4ec |
fix(#1714): drop nodes a11y allowlist entry — subsumed by #1720 (#1730)
## Summary PR #1720 (commit `a344ae0a`, merged 2026-06-13) introduced `--status-green-text=#15803d` (5.02:1 on white) and routed the `/analytics?tab=nodes` stat-card text usage to the new token. The remaining contrast violation that issue #1714 tracked is gone, so the allowlist entry is stale. ## Change Drop the single allowlist entry tagged `issue: 1714` from `tests/a11y-allowlist.yaml`: ```yaml - route: '/analytics?tab=nodes' selector: '.analytics-stat-card:nth-child(1) > div:nth-child(1)' rule: color-contrast issue: 1714 expires_at: 2026-09-11 ``` No other tabs touched (#1715/#1716/#1718 remain — separate issues, separate PRs). ## Verification The CI a11y gate (`test-a11y-axe-1668.js`) is the authoritative check. It re-renders `/analytics?tab=nodes` in dark+light × desktop+mobile and asserts zero net violations against the trimmed allowlist. With this PR, the entry is gone — if PR #1720's fix were ever reverted, the gate fails immediately (nothing left to mask it). Local repro was not attempted: prior PR #1723 (same allowlist-drop shape, same upstream PR #1720) documented sandbox chromium failures (musl/glibc + Vulkan/EGL); CI is the source of truth for this gate. Before (current `master`, with entry present): CI a11y gate green (the allowlist masks the now-fixed selector). After (this PR, entry removed): CI a11y gate must remain green because the underlying contrast was actually fixed by PR #1720. ## TDD note Config-change exemption per workspace AGENTS.md: - No test files modified. - No production code modified. - Config-only allowlist trim; CI must stay green without test edits. - The gate itself is the test — adding a duplicate assertion file would not catch anything CI does not already catch. Mirrors the exact pattern accepted in PR #1723 (subpaths allowlist drop, same upstream PR #1720 fix). ## Preflight `bash ~/.openclaw/skills/pr-preflight/scripts/run-all.sh origin/master` → all hard gates pass, all warnings pass. ("Red commit" gate notes this is a config-change with no test commits, justified above.) Partial fix for #1714 (will switch to `Fixes #1714` once CI a11y gate confirms zero net violations on `/analytics?tab=nodes`). Refs PR #1720, PR #1723. |
||
|
|
92e001c093 |
chore(a11y): drop subsumed subpaths allowlist entries (#1713) (#1723)
## Summary PR #1720 merged (commit `a344ae0a`) and introduced the shared `.btn-active-accent` color-contrast rule, which subsumes the per-link allowlist entries for the subpaths tab pills on `/analytics?tab=subpaths`. This PR removes the 4 now-stale allowlist entries tagged `issue: 1713`: - `a[href$="#sp-pairs"]` - `a[href$="#sp-triples"]` - `a[href$="#sp-quads"]` - `a[href$="#sp-long"]` All four were `rule: color-contrast` exemptions on `/analytics?tab=subpaths`. ## Verification CI a11y gate (`test-a11y-axe-1668.js`) is the authoritative check — it re-renders the route in dark+light × desktop+mobile and asserts zero net violations against the trimmed allowlist. Local repro was attempted but blocked by sandbox chromium issues (musl/glibc relocations on bundled playwright chromium; host chromium hits Vulkan/EGL init failures). Relying on CI a11y job for the green signal. ## TDD note Config exemption per workspace AGENTS.md: - No test files modified. - Config-only allowlist trim; CI must stay green without test edits. Partial fix for #1713 (will switch to `Fixes #1713` once CI a11y gate confirms zero net violations on `/analytics?tab=subpaths`). Co-authored-by: corescope-bot <bot@corescope> |
||
|
|
ae88d38b12 |
chore(a11y): drop subsumed clock-health allowlist entries (#1717) (#1722)
## Summary
Drops the two stale `issue: 1717` entries from
`tests/a11y-allowlist.yaml`. Both were subsumed by PR #1720 (merged at
|
||
|
|
69fba8032d |
test(a11y): expand axe CI gate to all 14 analytics tabs + prefix-tool (#1706) (#1711)
## Summary Closes #1706. Expands the axe-core a11y CI gate (`test-a11y-axe-1668.js`) to cover the 7 missing analytics tabs plus the `prefix-tool` utility surface. Before this PR, only 7 of 14 analytics tabs were gated; the other 7 could regress on contrast/aria without CI noticing. ## Changes **`test-a11y-axe-1668.js`** — adds 8 hash-routes to `ROUTES`: - `/analytics?tab=subpaths` - `/analytics?tab=nodes` - `/analytics?tab=distance` - `/analytics?tab=neighbor-graph` - `/analytics?tab=rf-health` - `/analytics?tab=clock-health` - `/analytics?tab=scopes` - `/analytics?tab=prefix-tool` The `prefix-tool` route was verified by greppping `public/analytics.js`: the dispatch arm is `case 'prefix-tool':` (line 292), the nav button uses `data-tab="prefix-tool"` (line 132), and existing UI cross-links use `#/analytics?tab=prefix-tool` (lines 1467, 1469, 1795, 3064). It lives in the analytics tab strip, not a separate `/tools/...` route. `REGISTERED_ANALYTICS_TABS` already lists all 15 tabs (the selftest's reciprocity check kept the constant honest), so no sibling slug-list at line ~82 needed updating beyond the existing list. **`test-a11y-axe-1668-selftest.js`** — adds a meta-assertion that loops over `REGISTERED_ANALYTICS_TABS` and asserts each `tab` has a matching `/analytics?tab=<tab>` entry in `ROUTES`. This locks the gate forever: any new analytics tab added to `analytics.js` will fail the selftest unless its route is also gated. ## TDD shape (red → green) - **Red commit** `a1d9aa8e` — adds the meta-assertion to the selftest. Selftest fails with `#1706: ROUTES missing analytics tab coverage for "/analytics?tab=subpaths"` (asserted, not a build error). - **Green commit** `501d9572` — adds the 8 missing entries to `ROUTES`. Selftest passes: `routes=24 themes=2 allowlist=0`. Cell count: 24 routes × 2 themes × 2 viewports = **96 cells** (was 64). ## Allowlist / tracking issues None yet. The 7 new analytics tabs and `prefix-tool` have not yet been exercised by the full axe browser run in CI — that happens when this PR runs. Per the M5 policy embedded in the gate's header, if any of the new routes fails axe on first run, a follow-up tracking issue + per-policy allowlist entry will be filed (the violations will NOT be silenced in this PR, and the routes will NOT be removed). I'll watch CI and report back. ## Out of scope Per the issue: - No keyboard-nav / focus-visible coverage (separate gap). - No modal / slideover open-state scans (separate gap). - No tufte / density work. - No source-code modifications to any analytics tab (contrast/aria fixes happen in follow-up PRs, not here). ## Preflight Ran `bash ~/.openclaw/skills/pr-preflight/scripts/run-all.sh origin/master` — all hard gates pass, no warnings. ## Verification ``` $ node test-a11y-axe-1668-selftest.js PASS: a11y-axe-1668 selftest — routes=24 themes=2 allowlist=0 ``` --------- Co-authored-by: clawbot <bot@kpa-clawbot.local> Co-authored-by: Kpa-clawbot <bot@openclaw.local> Co-authored-by: openclaw-bot <bot@openclaw> |
||
|
|
d954ea7444 |
feat(#1668): axe-core CI gate for WCAG AA color-contrast (M5) (#1696)
Partial fix for #1668 (M5 of 6). After M1 (audit), M2 (color tokens, #1676), M3 (typography floor, #1679), and M4 (per-route polish, #1681) cleared ~95% of contrast/typography violations, M5 **locks in the wins** by adding an axe-core CI gate that fails the build on any new WCAG AA color-contrast regression. ## What's in the box - `test-a11y-axe-1668.js` — Playwright + `@axe-core/playwright`. Runs every major CoreScope route × `{dark, light}` at 1200×900 desktop, injects axe, runs only the `color-contrast` rule, asserts net violations === 0. - `test-a11y-axe-1668-selftest.js` — fast, deterministic, browser-free unit test that exercises the YAML allowlist parser, the `violationAllowed` matcher, and the route/theme metadata. Runs in the JS unit block (no browser needed). - `tests/a11y-allowlist.yaml` — operator-flagged false-positive allowlist. **0 entries at M5 baseline.** ## Allowlist format Each entry MUST cite a GH issue # and an `expires_at` date. Missing fields = refused. Expired `expires_at` = refused (warning logged). This **forces a periodic revisit** — no permanent suppressions. ```yaml - route: /analytics?tab=channels selector: ".some-known-stale-element" rule: color-contrast issue: 1234 expires_at: 2026-09-01 ``` ## Routes covered (19 × 2 themes = 38 cells) `/`, `/packets`, `/nodes`, `/channels`, `/live`, `/map`, `/observers`, `/compare`, `/analytics?tab={overview,rf,topology,channels,hashsizes,collisions,roles,airtime}`, `/audio-lab`, `/customize`, `/replay`. ## TDD red→green - **RED** (`08adafdb`) — adds the gate + deliberately regresses `--text-muted` from `palette-gray-700` (~10:1) to `#9ca3af` (~2.4:1). axe-core fails on every light-theme cell. - **GREEN** (`f62fb1e0`) — restores the M2 token. Net violations = 0 across all 38 cells. ## Scope discipline - Only `color-contrast` (matches M2/M3/M4 scope). M6 owns `image-alt`, `aria-required-attr`, `label`, mobile viewports, and letsmesh A/B. - No new design tokens. - M2-M4 tokens untouched. ## CI wiring - `.github/workflows/deploy.yml:155` — selftest in JS unit block. - `.github/workflows/deploy.yml:367` — real axe browser run in the Playwright E2E block after the fixture server is up. ## Deps `@axe-core/playwright@4.11.3` + `axe-core@4.12.1` added to `devDependencies`. Pinned versions. --------- Co-authored-by: openclaw-bot <bot@openclaw.local> Co-authored-by: clawbot <clawbot@users.noreply.github.com> |
||
|
|
e74e860725 |
fix(#1648): final emoji leaks — .obs-clock-naive-chip warning + analytics Channels encrypted group labels (#1665)
## What Two Phosphor lint-gate breaches found by the v3.8.4 manual-test executor — app-controlled UI labels still shipping raw emoji glyphs that the M6 final sweep (#1648) missed. One PR, two sprite swaps, same playbook as #1657. ### Findings | Test ID | Surface | Glyph | File:line | Fix | |---|---|---|---|---| | v384-1.2 | `/observers` `.obs-clock-naive-chip` | `⚠️` (U+26A0) ×14 | `public/observers.js:30` | `ph-warning` sprite | | v384-12.18 | `/analytics?tab=channels` encrypted row name cells | `🔒` (U+1F512) ×158 | `public/analytics.js:978–979` | `ph-lock` sprite | Finding 2 is a different surface from the M3/#1657 fix (which swapped the section-header label, not the per-row `displayName`). The unknown-encrypted row's `displayName` carried a raw `🔒 Encrypted (0xNN)` text label that then flowed through `esc()` into the rendered name cell as an escaped emoji glyph — exactly the same `innerText → innerHTML` class of bug. Refactored to mirror the section-header pattern: `displayNameHtml` carries the sprite-bearing raw HTML; `displayName` stays plain text for sort/aria/tests. ## TDD - **RED** `cde12370` — `test-issue-1648-followup-phosphor-leaks.js` asserts ph-warning sprite + zero ⚠ in chip output, and ph-lock sprite + zero 🔒 in analytics row labels. 6 assertions failed on master. - **GREEN** `f1c64b17` — sprite swaps applied. All 9 assertions pass. - **Anti-tautology proven both directions**: reverting only `public/observers.js` → 2 chip-related assertions fail; reverting only `public/analytics.js` → 4 analytics-related assertions fail. ## Verify - ✅ `node test-issue-1648-followup-phosphor-leaks.js` — 9/9 pass - ✅ `node test-issue-1648-m6-final-sweep.js` — 0 violations - ✅ `node test-observer-naive-clock-1478.js` — 8/8 pass (existing chip test accepts ph-warning sprite) - ✅ `node test-analytics-channels-integration.js` — pre-existing unrelated `Channel Analytics` failure only; encrypted-row assertions all pass with new plain-text `displayName` - ✅ pr-preflight all gates green (PII, branch-scope, red-commit, CSS-var, LIKE-on-JSON, async-migration, XSS sinks) - ✅ Browser-verified on staging: 11 chips render ph-warning sprite (0 emoji), 156 ph-lock sprites in row name cells (0 lock emoji on page) Browser verified: http://analyzer-stg.00id.net/#/observers + /#/analytics?tab=channels (hot-patched) E2E assertion added: `test-issue-1648-followup-phosphor-leaks.js:67` (chip), `test-issue-1648-followup-phosphor-leaks.js:147` (row cell) --------- Co-authored-by: meshcore-bot <bot@meshcore.dev> |
||
|
|
89eade6e7b |
M6: emoji → Phosphor — final sweep, lint gate, carry-forwards (#1648) (#1654)
Red commit:
|