Skip to content

test: fix or retire the remaining orphan tests (#189) - #197

Merged
dborup merged 15 commits into
masterfrom
codex/issue-189-orphan-tests
Oct 4, 2026
Merged

dborup merged 15 commits into
masterfrom
codex/issue-189-orphan-tests

Conversation

@dborup-agent

Copy link
Copy Markdown
Collaborator

Relates to #189

This PR works through the orphan root tests that #187 left on KNOWN_UNREGISTERED in test-test-all.js. Each one is repaired and registered, ported, or kept on the list with a reason. The causes were traced in git history before any expectation was changed. Every repaired file was checked with at least one mutant of the production code, run in a copy of the tree and never committed, and each mutant turned the test red.

  • No production code changed. git diff origin/master...HEAD -- public/ is empty.
  • No npm dependencies added.
  • Fork guards unchanged: 9 × github.repository == 'Kpa-clawbot/CoreScope' in deploy.yml and 1 in release-fast-path.yml.
  • deploy.yml: the only change is five lines appended to the Playwright E2E list.

Result

Before (6f7a5e7c) After
Files in test-all.sh 201 211 (+10)
E2E files added to the Playwright step – 5
KNOWN_UNREGISTERED entries 18 3

The three entries that remain:

  • test-packets.js: one deliberately red assertion for the collapsed-caret bug;
  • test-touch-targets.js: waits on the 48 vs 44 px decision;
  • test-rx-coverage-mobile-nav-e2e.js: unchanged, it skips on purpose.

Unit files

File Outcome Cause (traced) Change Mutants (all red)
test-channel-colors.js fixed, registered 68a4628e (Kpa-clawbot#675) deliberately switched the row style to a 3px border with no tint asserts the exact border-left:3px solid …; for GRP_TXT and CHAN 3px → 4px
test-channel-ux-followup.js fixed, registered b812a98a (Kpa-clawbot#1648 M3) reworded the hint to "Use the close button…" and changed ✕ to #ph-x asserts the new copy, and that the remove button renders #ph-x hint reworded; remove glyph → #ph-trash
test-channel-ux-round2.js fixed, registered b812a98a: 📤 is now the #ph-share-network sprite + " Share" asserts that glyph argument " Share" dropped; icon dropped
test-drag-manager.js fixed, registered 2b45f787 (Kpa-clawbot#1567) uses removeAttribute('data-dragged'), and the mock's dataset was a separate object dataset is now a Proxy over the attribute map, like a DOMStringMap another attribute removed; dataset.dragged='false'
test-fluid-scaffolding.js fixed, registered f0addfda (Kpa-clawbot#1668) added a palette :root first, and the test read only the first block reads every top-level :root block with comments stripped; the last declaration wins --space-xs: 4px; --gutter removed; a later :root overrides --fs-md
test-hop-resolver-affinity.js fixed, registered 2b9f3056 (Kpa-clawbot#874), haversine: NodeB really was closer (70.88 vs 71.06 km). Green at 2b9f3056^, red at 2b9f3056 NodeA moved to (37.2, −122.2), about 43 km away against 71 km, and the geometry is asserted. Tests 1 and 5 now mean something: with the old fixture they stayed green with affinity disabled geo sort reversed; graph strategy disabled
test-issue-1470-card-bg-contrast.js fixed, registered e2212f50 (Kpa-clawbot#1627) added a comment containing [data-theme="dark"] parses style.css with comments removed dark --card-bg → surface-1
test-issue-1646-compare-polish.js fixed, registered d954ea74 (Kpa-clawbot#1668 M5) added a comment containing font-size:10px inside .compare-vs comments blanked, newlines kept .compare-vs 10px → 14px
test-perf-disk-io-1120.js reworked, registered 30627454: ⚠️ is now #ph-warning, and the four "no ⚠️" checks were passing vacuously. a26a412c (Kpa-clawbot#1593) replaced the backfill detector 8 flag checks match the sprite next to the value. The 2 backfill cases now test the page wiring of detectPerfAnomalies (history across refreshes, flag only on the spiking row, guard against less than 30 s of history). The detector itself is covered by test-perf-anomaly.js WAL > → >=; cache < → <=; WAL threshold ×10; row flag never rendered; history cleared each refresh; minHistorySec 0; flag on every row
test-table-sort.js ported (jsdom → vm), registered jsdom is not a dependency, so table-sort.js had no unit test small DOM shim inside the test; all 22 cases kept; the ▲/▼ cases now check the #ph-caret-up/down sprite (Kpa-clawbot#1648 M2) direction ignored; carets swapped; destroy() keeps aria-sort; rows not re-appended; custom comparator ignored; NaN sorts first
test-packets.js 12 of 13 fixed; stays unregistered 30627454 (Kpa-clawbot#1648 M2), emoji → sprites. The 13th failure is a real bug: a collapsed group shows #ph-caret-up 12 assertions now check the sprites. The caret assertion now expects #ph-caret-right and stays red; public/packets.js is left alone while #185 edits it envelope → chat-circle; eye dropped; room → broadcast. With the caret set to #ph-caret-right in a copy, the file is 128/128 green
test-touch-targets.js left on the list 48 px (upstream Kpa-clawbot#2078) vs 44 px (#85) needs a decision; the harness is also stale (see below) reason text only –

E2E files

File Outcome Cause Change Mutants (served from a copy, all red)
test-marker-outline-weight.js → test-live-pulse-ring-weight-e2e.js ported to plain playwright, registered @playwright/test ESM spec; nothing else covers the ≥2px pulse ring (Kpa-clawbot#1521) follows its own pulse frame by frame, requires both the 3px and the 2px phase, and fails if no pulse is queued (the old spec passed vacuously then) thin phase 2 → 1px; initial weight 3 → 1; pulseNode returns early
test-channel-modal-e2e.js updated, registered 70855249 (Kpa-clawbot#1227) changed the label to "+ Add"; 12d96a9d (Kpa-clawbot#1111) hides My Channels while it is empty checks the chip text and aria-label; expects no My Channels on a fresh page, then My Channels after the PSK add. Kept because ✕-close and PSK persistence are not covered elsewhere My Channels rendered while empty; close ignored; aria-label changed
test-node-reach-e2e.js fixed, registered L.map('nqMap') puts .leaflet-container on #nqMap itself, so the descendant selector never matched. It has been red since it was added in e2212f50. No real overlap: test-node-reach-coverage-e2e.js skips in CI (clientRxCoverage off) waits for #nqMap.leaflet-container, and only when the node has a location map never built; incoming/outgoing filters swapped
test-path-inspector-e2e.js ported, registered @playwright/test spec. Its prefixes 2c,a1 have no candidates in the CI fixture keeps what is not covered elsewhere: the map side pane (collapsed → expanded, candidate table, Show on Map draws .mc-rt-edge) and the Tools landing links. Finds a prefix pair through /api/paths/inspect (at most 400 probes) Show on Map draws nothing; pane always "No candidates"; pane starts expanded; Tools link renamed
test-issue-1522-trace-url-sync-e2e.js ported, registered @playwright/test spec; the Kpa-clawbot#1523 fix had no running test both cases kept and tightened: a request is made, history.length is unchanged (replaceState), and the deep link really traces replaceState removed; → pushState; deep-link auto-trace removed

Removed cases from the path-inspector spec, and the tests that cover them:

Case Covered by
standalone deep link test-path-inspector-coverage-e2e.js ("deep link ?prefixes=2c …")
#/traces/<hash> redirect test-issue-1883-redirect-history.js
"switching candidate clears prior polyline" nothing; it asserted nothing

Not done here

Verification (local, Linux, Node v22.23.3, Chromium 1208)

Run Result
sh test-all.sh before / after 201/201 → 211/211, exit 0
dash test-all.sh 211/211
test-all.sh in a copy without node_modules (like the CI unit job) 211/211
node test-test-all.js 8/8
each repaired unit file alone exit 0 (test-packets.js: exit 1, only the caret assertion)
5 registered E2E files, fixture server (CI recipe: freshen, Kpa-clawbot#1486/Kpa-clawbot#1791 seed, corescope-migrate, seed-2073), plain public/ 3/3 each
the same, public-instrumented/ (scripts/instrument-frontend.sh) 3/3 each
scripts/check-xss-sinks.sh --diff origin/master no public/ changes

🤖 Generated with Claude Code

https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv

dborup and others added 15 commits October 3, 2026 14:48
…189)

68a4628 (Kpa-clawbot#675) intentionally changed getRowStyle to a 3px left border
with no background tint (comment in channel-colors.js cites Kpa-clawbot#674). The
test still expected the old 4px border + 10% tint. Assert the exact
string for GRP_TXT and the CHAN alias.

Mutant: 3px -> 4px in channel-colors.js turns both cases red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…tests; register (#189)

b812a98 (Kpa-clawbot#1648 M3) replaced the ✕ and 📤 glyphs with Phosphor sprites:
the privacy hint now says "Use the close button to remove individual
channels", and the share button glyph is the #ph-share-network sprite +
" Share". Both were deliberate; the tests still asserted the emoji.

- test-channel-ux-followup.js: assert the new copy, and that the remove
  button it refers to renders the #ph-x close icon.
- test-channel-ux-round2.js: assert the share glyph argument is the
  aria-hidden #ph-share-network sprite + " Share".

Mutants (channels.js): hint reworded; remove glyph #ph-x -> #ph-trash;
" Share" dropped; icon dropped. Each turns its test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…utes; register (#189)

2b45f78 (Kpa-clawbot#1567) moved the Escape revert to clearPanel(), which calls
removeAttribute('data-dragged'). In a browser that also clears
dataset.dragged; the mock kept dataset and attributes in two separate
objects, so "Escape during drag reverts to corner position" saw a stale
dataset.dragged === 'true'. The code is right, the mock was not.

dataset is now a Proxy over the same attribute map, like a DOMStringMap.

Mutants (drag-manager.js clearPanel): remove a different attribute
instead of data-dragged; set dataset.dragged = 'false' instead of
removing it. Both turn the Escape test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…189)

f0addfd (Kpa-clawbot#1668 M2) added the palette :root block above the fluid
scaffolding block. The test read only the first :root, so all 13 token
checks failed although the tokens are still declared with clamp().

rootVar() now strips comments, scans every unconditional top-level
:root block (blocks nested in @media are skipped) and keeps the last
declaration, as the cascade does.

Mutants (style.css): --space-xs -> 4px; --gutter removed; a later
:root block overriding --fs-md with 14px. Each turns the test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…losest; register (#189)

2b9f305 (Kpa-clawbot#874) switched the geo fallback to haversine. NodeA (37,-122)
and NodeB (38,-123) were mirror images around NodeC in degrees, and by
haversine NodeB is the closer one (70.88 vs 71.06 km). The test passes
at 2b9f305^ and fails at 2b9f305: the resolver is right, the fixture
was wrong.

NodeA moves to (37.2,-122.2), ~43 km from NodeC vs ~71 km for NodeB,
and the test now asserts that geometry with HopResolver.haversineKm.
This also makes Tests 1 and 5 meaningful: with the old fixture they
still passed when affinity scoring was disabled, because NodeB won on
distance anyway.

Mutants (hop-resolver.js): geo sort reversed -> Test 2 (and the lat/lon=0
cases) red; graph strategy disabled -> Tests 1 and 5 red (green with the
old fixture).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…46 tests; register (#189)

Both tests parse style.css with indexOf/regex and were tripped by
comments added later, not by a CSS change:

- test-issue-1470-card-bg-contrast.js: e2212f5 (Kpa-clawbot#1627) added a comment
  mentioning [data-theme="dark"] above the real block, so indexOf landed
  on the comment and --card-bg was "not found". The dark block still
  sets var(--surface-2).
- test-issue-1646-compare-polish.js: d954ea7 (Kpa-clawbot#1668 M5) added a comment
  containing "font-size:10px+color:..." inside .compare-vs, and the
  font-size regex read the comment. Comments are blanked with their
  newlines kept, so the line-anchored @media helper is unaffected.

Mutants (style.css): [data-theme="dark"] --card-bg -> var(--surface-1);
.compare-vs font-size 10px -> 14px. Each turns its test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
….js; keep the caret check red (#189)

3062745 (Kpa-clawbot#1648 M2) replaced the row emoji in getDetailPreview and
buildGroupRowHtml with Phosphor sprites, one to one. 12 of the 13 red
assertions only checked the old emoji; they now check the aria-hidden
sprite (phIcon helper): chat-circle, broadcast, house-line, thermometer,
radio, lock, envelope, shuffle, eye.

The 13th is not stale. Before 3062745 a collapsed group showed ▶; the
migration mapped it to #ph-caret-up, so collapsed groups now show an up
caret. The assertion now expects #ph-caret-right (and not the expanded
#ph-caret-down) and stays red: public/packets.js is not touched here
while #185 edits it. test-packets.js stays on KNOWN_UNREGISTERED with
that reason until the caret is fixed.

Mutants (packets.js): TXT_MSG envelope -> chat-circle; eye icon dropped;
room icon -> broadcast. Each adds a failure. With the caret changed to
#ph-caret-right in a copy, the file is 128/128 green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…the rolling detector; register (#189)

Two things had moved under this test:

- 3062745 (Kpa-clawbot#1648 M2) replaced the ⚠️ flag with the #ph-warning sprite.
  The four "fires" checks failed, and the four "does NOT fire" checks
  passed vacuously because they looked for an emoji that is never
  rendered. All eight now match the sprite right after the value
  (flagged(html, value)); the negative checks also assert the value is
  rendered.
- a26a412 (Kpa-clawbot#1593) replaced the single-snapshot tx-ratio detector with
  detectPerfAnomalies (per-source 5-min rolling baseline, 30 s minimum
  history). The two backfill cases drove the old detector
  (window._perfWriteSourcesPrev, tx>=100 gate). The detector maths is
  covered by test-perf-anomaly.js, so these two cases now test the page
  wiring instead: three refreshes build history on window, the spiking
  source's row shows rate/baseline and the flag while a steady source's
  row does not, and a 10 s history suppresses the flag.

Mutants (perf.js): WAL > -> >=; cache < -> <=; WAL threshold 100 -> 1000;
row flag never rendered; history cleared every refresh; minHistorySec
30 -> 0; any flag rendered on every row. Each turns the test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…189)

jsdom was never a dependency, so this test could not run anywhere and
public/table-sort.js had no unit test (only the observers-sort E2E).

The file now loads table-sort.js with vm and a small DOM shim defined in
the test: attributes, classList, style, child lists with real moves on
appendChild, remove(), listeners + click(), cells, textContent, and a
selector engine for the few selectors table-sort.js uses. All 22 cases
are kept. The two arrow cases expected ▲/▼; Kpa-clawbot#1648 M2 switched the arrow
to the #ph-caret-up / #ph-caret-down sprite, so they check that now.

Mutants (table-sort.js): direction ignored; up/down carets swapped;
destroy() keeps aria-sort; rows not re-appended; custom comparators
ignored; NaN sorts first. Each turns the test red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…ster in CI (#189)

test-marker-outline-weight.js was an @playwright/test ESM spec, and
that runner is not a dependency, so it never ran. Kpa-clawbot#1521 rewrote it to
check that the canvas pulse highlight ring keeps a >= 2px stroke while
visible; nothing else covers that (test-live-dt-cap-1524.js only checks
stepPulse's dt cap).

Renamed to test-live-pulse-ring-weight-e2e.js and ported to the plain
playwright pattern of test-pr-1490-live-map-gpu-animations-e2e.js
(CHROMIUM_REQUIRE / SKIP, rAF awaited in the page). It follows the one
pulse it queues until the engine drops it, and requires frames in both
the 3px (hl_op > 0.4) and the 2px phase. The old spec also passed when
no pulse was queued (min over no frames = Infinity >= 2); the port
fails then.

Registered in the Playwright step of deploy.yml against the fixture
server. Fork guards unchanged (9).

Mutants (live.js, served from a copy): thin phase 2 -> 1px; initial
weight 3 -> 1; pulseNode returns before queueing. Each turns it red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
… and Kpa-clawbot#1111; register in CI (#189)

Two of its 14 steps were stale, not regressions:

- 7085524 (Kpa-clawbot#1227, Kpa-clawbot#1224 mobile UX) shortened the sidebar button to a
  "+ Add" chip; the accessible name is still "Add channel". The step now
  checks visibility, the chip text and the aria-label.
- 12d96a9 (Kpa-clawbot#1111) hides the My Channels section while this browser
  holds no key, so waiting for all three sections on a fresh page timed
  out. The step now expects Network + Encrypted and no My Channels, and
  a new last step expects My Channels with the channel the test added.

Kept (not deleted) because two steps are not covered elsewhere in CI:
clicking the close button hides the modal, and a valid PSK is persisted
under corescope_channel_keys. Registered in the Playwright step against
the fixture server. Fork guards unchanged (9).

Mutants (channels.js, served from a copy): My Channels rendered while
empty; close button ignored; aria-label changed. Each turns it red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
… in CI (#189)

The Reach page E2E timed out waiting for '#nqMap .leaflet-container'.
The map does render: L.map('nqMap') adds .leaflet-container to #nqMap
itself, so a descendant selector can never match. The test has been
red since it was added in e2212f5 (Kpa-clawbot#1627); it was never registered.

It now waits for '#nqMap.leaflet-container' (visible) and an attached
map pane, and only when the node itself has a location, which is when
node-reach.js builds the map.

Overlap with test-node-reach-coverage-e2e.js: none in practice. That
file tests the coverage layer only and skips in CI because the fixture
has clientRxCoverage off. This file is the only CI test of the Reach
endpoint shape, the toggles' row counts and the map.

Mutants (node-reach.js, served from a copy): map never built; incoming
and outgoing filters swapped. Each turns it red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…ster in CI (#189)

test-path-inspector-e2e.js was an @playwright/test spec (not a
dependency), so it never ran. Its fixed prefixes 2c,a1 also have no
candidates in the CI fixture, so the Show on Map cases could not pass
there anyway.

The port keeps what nothing else in CI covers: #mapSidePane collapsed
on load and expanded by the toggle; the pane's prefix search renders
one row per API candidate; Show on Map draws the route (.mc-rt-edge)
and enters route view; the Tools landing links to the Path Inspector
and to Trace. The prefix pair is found through /api/paths/inspect
(bounded at 400 probes) instead of being hard-coded.

Dropped, covered elsewhere: the standalone deep link
(test-path-inspector-coverage-e2e.js, "deep link ?prefixes=2c …") and
the #/traces redirect (test-issue-1883-redirect-history.js). "Switching
candidate clears prior polyline" asserted nothing. The coverage file's
header, which still called this spec unwired, is updated.

Registered in the Playwright step. Fork guards unchanged (9).

Mutants (served from a copy): Show on Map draws nothing (map.js); pane
results always "No candidates" (map.js); pane rendered expanded
(map.js); Tools landing link renamed (app.js). Each turns it red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…playwright; register in CI (#189)

test-issue-1522-trace-url-sync-e2e.js was an @playwright/test spec (not
a dependency), so the Kpa-clawbot#1523 fix (doTrace() writes #/tools/trace/<hash>
with replaceState) had no running test. test-e2e-playwright.js only
checks that the Trace page loads and returns results.

Ported to the plain playwright pattern. Both cases are kept and made
stricter: clicking Trace must issue GET /api/traces/<hash>, put the
hash in the URL and not grow history (replaceState, not pushState); a
deep link must pre-fill the input, actually run the trace and keep the
URL.

Registered in the Playwright step. Fork guards unchanged (9).

Mutants (traces.js, served from a copy): replaceState removed;
replaceState -> pushState; deep-link auto-trace removed. Each turns it
red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
…189)

The 48 vs 44 px decision for .nav-btn and .ch-icon-btn is left to the
maintainer: #85 kept 44 (WCAG 2.5.5), and upstream later closed 2052
with 48 (Kpa-clawbot#2078). The harness is also stale independently of that
decision (no viewport meta, so mobile-only controls render 0x0; it
still lists .compare-btn, removed in Kpa-clawbot#1646). Reason text only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY43YSM5M2JfDKYYxociMv
@dborup-agent

Copy link
Copy Markdown
Collaborator Author

Rapport — CS-pve-agent2 PR#197 #189 orphan tests — head c9c085b

Status: Draft, CI green. 15 of the 18 orphan entries are resolved (10 unit files registered, 5 E2E files registered), and 3 remain on KNOWN_UNREGISTERED: the caret bug in test-packets.js, the 48/44 decision for test-touch-targets.js, and the deliberate rx-coverage skip.

Evidence tags: [T] run here (local test or CI), [A] analysis of source/history, [K] taken from the issue or another PR's text and not re-run.

Files

File Outcome Cause Mutant(s) Replaced by / registered in
test-channel-colors.js fixed 68a4628e (Kpa-clawbot#675) deliberately switched to a 3px border-only row style [A] 3px → 4px: red [T] test-all.sh
test-channel-ux-followup.js fixed b812a98a (Kpa-clawbot#1648 M3) reworded the hint, ✕ → #ph-x [A] hint reworded / remove glyph → #ph-trash: red [T] test-all.sh
test-channel-ux-round2.js fixed b812a98a: 📤 → #ph-share-network + " Share" [A] " Share" dropped / icon dropped: red [T] test-all.sh
test-drag-manager.js fixed (mock) 2b45f787 (Kpa-clawbot#1567) removeAttribute; the mock's dataset was a separate object [A] other attribute removed / dataset.dragged='false': red [T] test-all.sh
test-fluid-scaffolding.js fixed (parser) f0addfda (Kpa-clawbot#1668) added an earlier :root block [A] --space-xs fixed px / --gutter removed / later :root override: red [T] test-all.sh
test-hop-resolver-affinity.js fixed (fixture) 2b9f3056 (Kpa-clawbot#874) haversine; green at 2b9f3056^, red at 2b9f3056 [T] geo sort reversed / affinity disabled: red [T]. The second mutant was green with the old fixture [T] test-all.sh
test-issue-1470-card-bg-contrast.js fixed (parser) e2212f50 (Kpa-clawbot#1627) comment containing [data-theme="dark"] [A] dark --card-bg → surface-1: red [T] test-all.sh
test-issue-1646-compare-polish.js fixed (parser) d954ea74 (Kpa-clawbot#1668 M5) comment containing font-size:10px [A] .compare-vs 10 → 14px: red [T] test-all.sh
test-perf-disk-io-1120.js reworked 30627454 ⚠️ → #ph-warning (4 negatives were vacuous); a26a412c (Kpa-clawbot#1593) new detector [A] 7 mutants (boundaries, threshold, flag, history, minHistorySec, flag on every row): all red [T] test-all.sh; detector maths stays in test-perf-anomaly.js
test-table-sort.js ported jsdom → vm jsdom not a dependency [A] 6 mutants (direction, carets, destroy, reorder, custom comparator, NaN): all red [T] test-all.sh
test-packets.js 12/13 fixed, still unregistered 30627454 emoji → sprites [A]. The 13th is the caret bug (see below) 3 sprite mutants red [T]; with the caret fixed in a copy: 128/128 green [T] stays on KNOWN_UNREGISTERED
test-touch-targets.js left on the list decision pending (below) – stays on KNOWN_UNREGISTERED
test-marker-outline-weight.js ported, renamed test-live-pulse-ring-weight-e2e.js @playwright/test spec, never ran; nothing else covers the ≥2px ring (Kpa-clawbot#1521) [A] thin phase 1px / initial 1px / no pulse queued: red [T]. The old spec passed vacuously when no pulse was queued [A] Playwright step
test-channel-modal-e2e.js updated 70855249 (Kpa-clawbot#1227) "+ Add" chip; 12d96a9d (Kpa-clawbot#1111) My Channels hidden while empty [A] My Channels while empty / close ignored / aria-label: red [T] Playwright step
test-node-reach-e2e.js fixed (selector) .leaflet-container sits on #nqMap itself; red since e2212f50 [T]. No CI overlap: the coverage E2E skips (clientRxCoverage off) [A] no map / toggles swapped: red [T] Playwright step
test-path-inspector-e2e.js ported @playwright/test spec; 2c,a1 has no candidates in the CI fixture [T] 4 mutants (Show on Map, results, pane state, Tools link): red [T] Playwright step. Deep link → test-path-inspector-coverage-e2e.js; #/traces redirect → test-issue-1883-redirect-history.js
test-issue-1522-trace-url-sync-e2e.js ported @playwright/test spec; Kpa-clawbot#1523 had no running test [A] no replaceState / pushState / no deep-link trace: red [T] Playwright step
test-rx-coverage-mobile-nav-e2e.js unchanged skips on purpose (clientRxCoverage off) [K] – stays on KNOWN_UNREGISTERED

Proposal: 48 vs 44 px for .nav-btn and .ch-icon-btn (not decided here)

Facts

  • Current CSS: .nav-btn and .ch-icon-btn have min-width/min-height: 44px, and every other control in the touch-target block has 48px. The stylesheet comment calls 48 the "house preference" [A].
  • test-touch-targets.js measures .nav-btn and .ch-icon-btn at 44.0×44.0 [T].
  • fix(css): unify compact touch target sizes #85 (merged 2026-09-25) took option 1 of upstream issue 2052: keep 44, remove the 48 declarations. It recorded clipped share/remove buttons at 768–1330 px as a known limitation [K].
  • Upstream then closed 2052 with option 2, 48px, in upstream PR fix(ui): use consistent 48px navigation and channel buttons Kpa-clawbot/CoreScope#2078 (merged 2026-09-30) [A, read-only]. That PR removes the 44px component rules and the legacy 32px rule. It also lets the controls of user-added channel rows wrap at 768 px so share/remove stay inside the sidebar. Its description says navigation height is unchanged [K].
  • WCAG 2.5.5 (AAA) asks for 44×44, and 48 satisfies it. The fork's test-issue-2052-touch-target-css.js and -e2e.js assert ≥44, so they stay green at 48 [A].

Recommendation: 48px, by porting upstream Kpa-clawbot#2078 in its own PR.

  1. It removes the only two exceptions to the stylesheet's own 48px rule. That inconsistency is exactly what 2052 was about.
  2. It matches upstream's final decision, so later upstream ports do not conflict around these rules in style.css.
  3. fix(ui): use consistent 48px navigation and channel buttons Kpa-clawbot/CoreScope#2078 also addresses the 768 px clipping that fix(css): unify compact touch target sizes #85 left as a known limitation.
  4. Cost: navbar buttons and channel row icons grow by 4px. This needs a check at 375, 390, 768 and 1280 px, on navbar height and channel row layout.

After that port, test-touch-targets.js can expect a uniform 48 and be registered. Its harness also has to change, whatever the decision:

If 44 is kept instead:

  • pin .nav-btn and .ch-icon-btn at 44 in test-touch-targets.js, the way upstream's interim MIN_OVERRIDES table did, so a third selector at 44 still fails;
  • fix the same harness issues;
  • correct the stale "Same 48x48 minimums … meet WCAG 2.5.5" comment in style.css, which still over-claims.

Remaining: collapsed packet groups show an up-caret (not fixed)

Counts

  • test-all.sh: 201 → 211 files, all green [T]. The 10 new files are under # Repaired orphans (#189).
  • KNOWN_UNREGISTERED: 18 → 3 [T].
  • Playwright step: +5 lines, appended to the existing list [T]. Fork guards: deploy.yml 9 → 9, release-fast-path.yml 1 → 1 [T].

E2E results (local) [T]

Fixture server built with CI's recipe:

Servers were stopped by port/pid, and the served tree was checked first.

File plain public/ public-instrumented/
test-live-pulse-ring-weight-e2e.js 3/3 (4/4 steps) 3/3
test-channel-modal-e2e.js 3/3 (15/15) 3/3
test-node-reach-e2e.js 3/3 3/3
test-path-inspector-e2e.js 3/3 (6/6) 3/3
test-issue-1522-trace-url-sync-e2e.js 3/3 (3/3) 3/3

Mutants for the E2E files ran on a second server that served a mutated copy of public/. Each run first confirmed that the mutated file was actually being served [T].

CI (run 37132401311, head c9c085b) [T]

Job Result
✅ Go Build & Test success. Run JS unit tests (test-all.sh) on Node v22.23.3: 211 passed, 0 failed (211 files)
🎭 Playwright E2E Tests success. All 5 new files ran on the instrumented fixture server, none skipped: pulse ring 4/4 (34 frames, 19 thick + 15 thin), channel modal 15/15, node-reach OK, path inspector 6/6 (pair 04,0a), trace URL sync 3/3
🏗️ Build & Publish Docker Image success
📦 Release Artifacts / 🚀 Deploy Staging / 📝 Publish Badges & Summary skipped (PR run)

Known remaining items

  • The caret bug and test-touch-targets.js, both above.
  • test-packets.js stays out of CI until the caret is fixed: 127 green assertions are not running there. An alternative is to move the caret assertion into its own red file and register test-packets.js now. I did not do that because it would start the caret work, which was out of scope.
  • Observation, not a test failure [T]: on #/map, once a Path Inspector route is shown, the route view (body.mc-route-active) moves #leaflet-map over the still-expanded Path Inspector pane. Choosing another candidate means closing the route view first. This looks like the intended full-page route mode, so I did not change it.
  • The P3 follow-ups in the issue comment were not addressed here: a commented deploy.yml line counting as registered, the list size not pinned, Node not pinned in the unit job, the 1705/1719 gates, and no per-file timeout.

@dborup-agent

Copy link
Copy Markdown
Collaborator Author

Review — CS-pve-agent1 PR#197 orphan tests — head c9c085b

Dom: APPROVE med nits

This review is read-only and independent. I tested git archive copies of head c9c085bf and of the merged tree. Master 6f7a5e7c is the merge base, so the merge is a fast-forward and the merged tree is the same as the head tree (c7876e2c). git ls-remote showed the same refs before and after the review: head c9c085bf, master 6f7a5e7c.

Evidence tags:

  • [T] I ran it myself.
  • [A] I checked it by reading source or git history.
  • [K] I took it from the PR, the author's report, or CI, and did not re-run it.

Findings

# Sev File Finding
1 nit test-test-all.js (KNOWN_UNREGISTERED) The reason for test-touch-targets.js still says "48px (upstream Kpa-clawbot#2078) vs 44px (#85) is pending a decision". The maintainer has decided: 48px, through a separate port of upstream Kpa-clawbot#2078. Reword it to something like "waits for the upstream Kpa-clawbot#2078 port (48px); harness also stale". The "Not done here" section of the PR description should say the same. [A]
2 nit test-channel-modal-e2e.js The reason for keeping the file is overstated. The PR says it is kept because "✕-close and PSK persistence are not covered elsewhere". But PSK persistence (corescope_channel_keys in localStorage, and the row appearing under My Channels) is already asserted by test-channels-add-modal-e2e.js in CI. Hiding My Channels while empty (Kpa-clawbot#1111) is asserted by test-channel-issue-1111-e2e.js, also in CI. What only this file covers: the ✕-close assertion (test-e2e-playwright.js only clicks it), the three section titles, the privacy footer, the case-sensitivity warning, the QR placeholders, and Encrypted being collapsed by default. That is enough to keep a file that takes about 2 s; only the wording needs to change. [A]
3 nit test-table-sort.js The port is faithful. My mutant that drops localStorage.setItem(storageKey, …) survived, so sort persistence and restore have no test. The jsdom original had the same gap, so the port did not lose anything. This could be an optional follow-up. My dBm-suffix mutant also survived, but it is equivalent: parseFloat already ignores the trailing " dBm". [T]
4 nit test-node-reach-e2e.js Steps 3 and later only run if the fixture has the right data. In the current CI fixture they do run: the first repeater has lat 37.888, 3 reliable tokens and 1 link with GPS, 0 of them two-way and 0 we-only. So the map check and the outgoing toggle are exercised, but the incoming toggle is only checked with no change in row count. This was the design before this PR. Consider failing when the fixture no longer provides tokens and links, so a fixture change cannot quietly reduce the test to a smoke test. [T]
5 nit PR description It says "the only change is five lines appended". The change is 5 run lines plus 1 comment line. [T]
6 info test-packets.js 127 green assertions stay out of CI until the caret is fixed. That matches the maintainer's decision to wait for #185. The author's alternative is to move the caret assertion into its own file; that is optional and not needed for this PR. [A]

None of these block the PR.

1. No weakened tests

Every changed expectation follows a deliberate code change, and I confirmed each commit in git history [A]:

  • test-channel-colors.js: 68a4628e (fix: channel color picker — data shape mismatch + redesign for discoverability Kpa-clawbot/CoreScope#675) changed return 'border-left:4px …;background:…1a;' to 'border-left:3px solid ' + color + ';'. The new strictEqual is stricter than before: it also fails if the background tint comes back.
  • test-channel-ux-followup.js and test-channel-ux-round2.js: in b812a98a, "Use ✕ to remove" became "Use the close button to remove". 📤 became #ph-share-network followed by " Share".
  • test-drag-manager.js: 2b45f787 replaced delete dataset.dragged with removeAttribute('data-dragged'). The new Proxy dataset behaves like a live DOMStringMap. I ran the master mock against current code and it is red on the Escape case [T].
  • test-fluid-scaffolding.js: f0addfda added the palette :root block first. The parser now skips nested blocks inside @media and lets the last declaration win.
  • test-hop-resolver-affinity.js: 2b9f3056 switched to haversine. With the old test, current code fails only "Should pick NodeA (geo-closest)", 16/17 [T].
  • test-issue-1470-card-bg-contrast.js and test-issue-1646-compare-polish.js: e2212f50 and d954ea74 added comments that contain the strings the parsers search for. Stripping comments is the right fix; no expected value changed.
  • test-packets.js: in 30627454, each of the nine emoji maps one to one to the sprite the test now expects. I counted removed versus added lines in that commit's packets.js diff: 💬→chat-circle, 📡→broadcast ×2, 🏠→house-line, 🌡→thermometer, 📻→radio, 🔒→lock ×4, ✉️→envelope, 🔀→shuffle, 👁→eye [A]. The caret assertion is red on purpose. The source confirms ▶ → #ph-caret-up [A], and the run gives 127 passed, 1 failed [T].
  • test-perf-disk-io-1120.js: a26a412c removed the old MIN_SAMPLE = 100 tx guard and added detectPerfAnomalies with minHistorySec 30. Dropping the old "tx<100 guard" case is therefore correct, and the new "<30 s history" case tests the guard that exists now. test-perf-anomaly.js is registered and covers the detector itself [A].

My own mutants, run in a copy of the tree. Each one is mine and differs from the author's.

Group Test Mutant Result
CSS parser test-fluid-scaffolding.js --space-xs declaration commented out, so the only clamp() left is inside a comment red [T]
CSS parser test-fluid-scaffolding.js --gutter moved into @media (min-width:1px) { :root { … } } (nested, not top-level) red [T]
CSS parser test-issue-1470-card-bg-contrast.js [data-theme="dark"] --card-bg commented out (line 481) red [T]
CSS parser test-issue-1470-card-bg-contrast.js @media dark --card-bg → surface-3 red [T]
CSS parser test-issue-1646-compare-polish.js real .compare-vs font-size removed; the comment with font-size:10px left in place red [T]
DOM text test-channel-colors.js background tint added back red, 2 cases [T]
DOM text test-channel-ux-followup.js remove icon #ph-x → #ph-x-circle red [T]
DOM text test-channel-ux-followup.js privacy hint sentence removed red [T]
DOM text test-channel-ux-round2.js share icon → #ph-export red [T]
DOM text test-channel-ux-round2.js " Share" removed from the glyph red [T]
mock test-drag-manager.js removeAttribute('data-drag') (wrong attribute) red [T]
mock test-drag-manager.js setAttribute('data-dragged','') instead of remove red [T]
mock test-drag-manager.js dataset.isDragged='true' on detach red [T]
fixture test-hop-resolver-affinity.js graph sort ascending (lowest edge score wins) red (Test 5) [T]
fixture test-hop-resolver-affinity.js graph strategy only when ≥2 candidates have edges red (Test 1) [T]
fixture same mutant, old test file — Test 1 stays green, which confirms the author's point that the old fixture was vacuous [T]
port test-table-sort.js default direction swapped (text → desc) red, 2 cases [T]
port test-table-sort.js persistence setItem removed survived (finding 3) [T]
E2E test-issue-1522-trace-url-sync-e2e.js replaceState → location.hash = … red, "history grew from 2 to 3" [T]
E2E test-live-pulse-ring-weight-e2e.js thin phase hl_op > 0.1 ? 3 : 1 (short, late dip) red, "dropped to 1 at hl_op 0.07" [T]

2. Ports

  • test-table-sort.js (jsdom → vm): all 22 case names are the same as before. Apart from building the DOM, the only assertion changes are ▲/▼ → #ph-caret-up/down, which matches Migrate emoji UI to Phosphor Icons (regular weight) — tracking Kpa-clawbot/CoreScope#1648 M2 [A]. The shim's selector engine supports only what table-sort.js uses, and throws on any other selector, so an unsupported selector cannot pass by accident. No other test covered table-sort.js before (test-frontend-helpers.js only mentions it in a comment) [A].

  • test-marker-outline-weight.js → test-live-pulse-ring-weight-e2e.js: it keeps the original goal: the ring stays ≥2px while it is visible (Additional live map performance optimizations Kpa-clawbot/CoreScope#1521). It is stricter than the old spec: it follows its own pulse object, requires frames in both the thick and the thin phase, and fails if no pulse is queued. test-live-dt-cap-1524.js only sets hl_weight in a fixture, so there is no overlap [A]. The new name is accurate.

  • test-path-inspector-e2e.js: it keeps the map side pane (collapsed → expanded), the candidate table, Show on Map drawing .mc-rt-edge, and the Tools landing. The dropped cases really are covered elsewhere:

    • the deep link, by test-path-inspector-coverage-e2e.js ("deep link ?prefixes=2c"), in CI;
    • the #/traces/<hash> redirect, by test-issue-1883-redirect-history.js (['#/traces/a1b2c3d4', '#/tools/trace/a1b2c3d4']), in test-all.sh [A].

    The pair search is capped at 400 probes. In CI and locally it finds 04,0a [T].

  • test-issue-1522-trace-url-sync-e2e.js: both original cases are kept. They now also check that the trace request is sent, that history.length does not change (replaceState), and that the deep-link trace renders [A]. No other test covers Trace tool: packet hash not reflected in URL (unsharable results) Kpa-clawbot/CoreScope#1522/fix: sync packet hash into URL after trace Kpa-clawbot/CoreScope#1523 [A].

  • Overlap with tests already in CI: only test-channel-modal-e2e.js overlaps (finding 2). test-node-reach-e2e.js and test-issue-1630-reach-mobile-e2e.js both use #nqMap, but 1630 only checks the map height [A].

3. Registration

  • test-all.sh: 201 → 211 run lines, and the 10 new ones are under # Repaired orphans (#189) [T].
  • KNOWN_UNREGISTERED: 18 → 3 entries (test-packets.js, test-touch-targets.js, test-rx-coverage-mobile-nav-e2e.js). None of the 3 appears in test-all.sh or in an uncommented line of deploy.yml, and no other test file is unregistered [T].
  • The deleted test-marker-outline-weight.js has no references left, apart from the "Previously …" comment in its replacement [T].
  • deploy.yml: the 5 new lines follow the pattern CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node … 2>&1 | tee -a e2e-output.txt. They come after test-packet-trace-alignment-e2e.js, inside the same fail-fast step [A].
  • Fork guards (github.repository == 'Kpa-clawbot/CoreScope'): 9 in deploy.yml, the same as on master, and 1 in release-fast-path.yml, which this PR does not touch [T].
  • CI time: in CI run 37132401311 the 5 files ran from 15:49:44 to 15:49:51.9, about 9 s in total [K: CI log timestamps]. Locally they took about 11 s [T]. The whole E2E step takes about 17–20 min, so the extra time is negligible. test-all.sh takes about 13 s locally [T].

4. Runs

Run Result
sh test-all.sh, merged tree, no node_modules (like the CI unit job), Node v22.23.3 211 passed, 0 failed (211 files), exit 0 [T]
node test-test-all.js 8 passed, 0 failed [T]
node test-packets.js 127 passed, 1 failed (only the caret assertion), as intended [T]
Go server built from the merged tree. Fixture prepared like CI: freshen-fixture.sh, the Kpa-clawbot#1486/Kpa-clawbot#1791 SQL block taken from deploy.yml, corescope-migrate, seed-2073-route-adverts.sql. Served public-instrumented/ on its own port; I checked that __coverage__ was being served —
test-live-pulse-ring-weight-e2e.js 4/4 (34 frames, 20 thick + 14 thin) [T]
test-channel-modal-e2e.js 15/15 [T]
test-node-reach-e2e.js OK, map branch exercised [T]
test-path-inspector-e2e.js 6/6 (04,0a) [T]
test-issue-1522-trace-url-sync-e2e.js 3/3 [T]

E2E mutants ran on a second server that served a mutated copy of public/ against a copy of the database. Before each run I checked with curl that the mutated file was the one being served. I stopped both servers with fuser -k <port>/tcp and confirmed that both ports were free afterwards [T].

5. Production code

git diff --stat 6f7a5e7c c9c085bf -- public/ cmd/ is empty. package.json, package-lock.json and release-fast-path.yml are also unchanged. Outside test files, the diff touches only .github/workflows/deploy.yml (+6) and test-all.sh (+12) [T].

Not verified

  • I did not re-run the author's own mutants; my mutants are different ones.
  • I ran the 5 E2E files only against public-instrumented/, not against plain public/. The plain-public/ copy was used only for the two E2E mutants.
  • I did not run dash test-all.sh, the rest of the E2E suite, or the Go tests (no Go code changed).
  • I did no browser or visual check; this PR has no UI change.
  • The caret bug and the 48px touch-target port are out of scope. I did not read upstream fix(ui): use consistent 48px navigation and channel buttons Kpa-clawbot/CoreScope#2078.
  • The CI results come from the run logs [K], not from a re-run.

@dborup
dborup marked this pull request as ready for review October 4, 2026 05:57
@dborup
dborup merged commit 33b0dfe into master Oct 4, 2026
6 checks passed
adminopenclaw8-sketch pushed a commit that referenced this pull request Oct 4, 2026
Resolve test-test-all.js: keep master's KNOWN_UNREGISTERED (#197) and
drop the test-touch-targets.js entry, which this branch registers in
the Playwright step of deploy.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants