Make `test-all.sh` the authoritative standalone frontend runner for npm
and CI. Restore stale assertions and reject missing, duplicate, removed
or undocumented inventory entries.
Fixes#1858.
Rebased onto `a2f039d4`. Retains release-routing, map scope-state and
Scope Audit stylesheet tests, adds `test-packets-local-channels.js` to
the sorted runner, and classifies `test-neighbor-map-btn-clip-e2e.js`
under browser. Its separate CI browser step is preserved. Inventory: 280
root suites, 167 standalone, 113 requiring separate setup.
The icon repair fixes two suites red on master:
`test-issue-1648-m2-emoji-scan.js` and
`test-issue-1648-m6-final-sweep.js`. Node/live configured-scope
confirmations now use the existing accessible Phosphor check sprite.
Values, visibility conditions and scanner assertions are preserved.
- Red evidence: `89e45a9` inventory assertions; `4e255df` accessible
confirmation assertion. The latest rebase also reproduced both
unclassified-file failures before adding their entries. This follow-up
only changes runner/classification configuration and counts; no test
files modified.
- Local validation: all 167 standalone suites; 27 M2 browser checks and
16 neighbor geometry checks in Chromium. Syntax, whitespace, PII,
CSS-variable and XSS checks passed.
- Browser coverage includes populated/empty/null configured scopes in
node and live views.
- No new dependencies, requests, application settings or Go changes.
Workflow outside the unit step matches master.
- Windows validation uses process-local UTF-8 settings. Encoding and
node-reach confirmation follow-ups remain separate, as requested.
## Preflight override
External `run-all.sh` is unavailable; applicable repository checks were
run directly.
Continues #1880 by @SaarMesh-Bot. Their commit is unchanged and keeps
their authorship; I added the lock file it was missing.
## What was wrong
#1880 added `eslint@^8.57.1` to `devDependencies` but not to
`package-lock.json`. CI runs `npm ci --production=false`, which requires
the two to be in sync, so the pipeline died at **Install npm
dependencies** before a single test ran:
```
npm error code EUSAGE
npm error `npm ci` can only install packages when your package.json and
npm error package-lock.json are in sync.
npm error Missing: eslint@8.57.1 from lock file
npm error Missing: @eslint-community/eslint-utils@4.10.1 from lock file
```
I approved that PR on 2026-08-30 on the grounds that it was two lines of
devDependency with no runtime effect. I checked that `.eslintrc.json`
exists so `npm run lint` would resolve, and did not check the lock file.
That was the miss.
## What this adds
One commit: the regenerated `package-lock.json`.
Generated with `npm install --package-lock-only`, so `node_modules` was
never touched and the change is confined to the lock file. The 13
removed lines are npm reorganising the existing `find-up` /
`find-cache-dir` entries because eslint brings its own versions of them;
nothing unrelated was bumped.
## Verification
| command | result |
|---|---|
| `npm ci --production=false` | **added 394 packages**, exit 0 |
| `npm run lint` | exit 0, **92 problems (0 errors, 92 warnings)** |
The warnings are pre-existing unused-variable reports across
`public/*.js`. Not addressed here: the point of this PR is that the
command runs at all, and whether to act on 92 warnings is a decision for
#1859 rather than something to smuggle in behind a lock file.
## Why this matters beyond itself
#1881 is the other half of #1859 and adds the gofmt/go vet CI gate. It
has been sitting at the end of the merge order all day because it forces
a rebase on every open Go PR. It also should not land before this one:
the `lint` script it complements is not installable until the lock file
is right.
@SaarMesh-Bot — your work, your credit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Wzwr3eXseyNM7Xj598djjE
---------
Co-authored-by: SaarMesh-Bot <300107934+SaarMesh-Bot@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
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>
## Summary
Fixes#485 — the app version was derived from `package.json` via
Node.js, which is a meaningless artifact for this Go project. This
caused version mismatches (e.g., v3.3.0 release showing "3.2.0") when
someone forgot to bump `package.json`.
## Changes
### `manage.sh`
- **Line 43**: Replace `node -p "require('./package.json').version"`
with `git describe --tags --match "v*"` — version is now derived
automatically from git tags
- **Line 515**: Add `--force` to `git fetch origin --tags` in setup
command
- **Line 1320**: Add `--force` to `git fetch origin --tags` in update
command — prevents "would clobber existing tag" errors when tags are
moved
### `package.json`
- Version field set to `0.0.0-use-git-tags` to make it clear this is not
the source of truth. File kept because npm scripts and devDependencies
are still used for testing.
## How it works
`git describe --tags --match "v*"` produces:
- `v3.3.0` — when on an exact tag
- `v3.3.0-3-gabcdef1` — when 3 commits after a tag (useful for
debugging)
- Falls back to `unknown` if no tags exist
## Testing
- All Go tests pass (`cmd/server`, `cmd/ingestor`)
- All frontend unit tests pass (254/254)
- No changes to application logic — only build-time version derivation
Co-authored-by: you <you@example.com>
- Install nyc for Istanbul instrumentation
- Add scripts/instrument-frontend.sh to instrument public/*.js
- Add scripts/collect-frontend-coverage.js to extract window.__coverage__
- Add scripts/combined-coverage.sh for combined server+frontend coverage
- Make server.js serve public-instrumented/ when COVERAGE=1 is set
- Add test:full-coverage npm script
- Add public-instrumented/ and .nyc_output/ to .gitignore
Proof of concept: bare Playwright (not @playwright/test) running 8 critical
flow tests against analyzer.00id.net:
- Home page, nodes, map, packets, node detail, theme customizer, dark mode, analytics
- Uses system Chromium on ARM (Playwright bundled binary doesn't work on musl)
- Not added to test-all.sh or CI yet — POC only
- Run with: node test-e2e-playwright.js
npm test: all tests + coverage summary
npm run test:unit: fast unit tests only
npm run test:coverage: full suite + HTML report in coverage/
Baseline: 37% statements, 42% branches, 54% functions
Fixed e2e channels crash (undefined .length on null)
Previously db.seed() ran unconditionally on startup and would populate
a fresh database with fake test data. Now seeding only triggers when
explicitly requested via --seed CLI flag or SEED_DB=true env var.
The seed functionality remains available for developers:
node server.js --seed
SEED_DB=true node server.js
node db.js (direct run still seeds)