Skip to content

ci: measure and shard Playwright E2E suites (#434) - #436

Merged
dborup merged 8 commits into
masterfrom
codex/issue-434-e2e-shards
Oct 13, 2026
Merged

dborup merged 8 commits into
masterfrom
codex/issue-434-e2e-shards

Conversation

@dborup

@dborup dborup commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Relates to #434

Summary

Split the existing 155 Playwright suites into three independently starting shards using measured longest-first (LPT) assignment. Each shard retains baseline-relative execution order and prepares its own unchanged fixture/server on localhost ports 13581, 13582 and 13583.

The checked-in manifest includes every assignment, command environment, three measured timing samples and provenance. The permanent three-repeat slide-over gate is bundled with its regular suite and runs exactly once on shard 3. Core frontend coverage belongs to shard 2.

The required check remains 🏗️ Build & Publish Docker Image. It explicitly requires Go, all three shards, the verified shard report and image validation to report success. Failure, skipped, cancelled and empty results fail the gate; a cancelled workflow does not turn the required gate green.

Draft only; auto-merge off. Latest head fa84117f is fully green in automatic PR run 38452595221, attempt 1, with seven successful jobs and three skipped. It includes the required ordinary master merges for issue #426 hardening and #427. Five completed successful post-change PR executions are reported separately below; failed historical executions remain disclosed, not hidden or claimed fixed. Nothing is marked ready, merged or deployed.

Measurement first

Downloaded full logs of three recent green PR runs: 38404492174, 38392091612 and 38391488315. None contained runtime === E2E SUITE: ... === markers; the green #383 log was also unmarked. Echoed shell commands are not runtime evidence, so no per-suite values were invented from those logs.

A marker-only baseline was therefore committed first. Removing its paired START/END echoes reproduced the then-current workflow byte-for-byte. Three full, fresh green attempts of the same PR run/head were collected before choosing assignments: run 38410864651, attempts 1–3, head 529e008c941f86c1901e21a62da85173e739200d. These are three distinct executions/job IDs, not three distinct GitHub run IDs.

Baseline execution Full E2E job All executed runner minutes Full execution span
38410864651, attempt 1 22m44s 46.83 23m27s
38410864651, attempt 2 28m43s 53.93 28m57s
38410864651, attempt 3 28m14s 51.17 28m26s
Mean 26m33.7s 50.64 26m56.7s

Runner minutes are the sum of actual non-skipped job start-to-completion durations, not billed/rounded minutes. Execution span excludes queue and idle wait between reruns. Measurements are wall time, so hosted-runner variability is visible.

Measured three-way assignment

Greedy assignment sorts by descending mean suite duration, with filename then shard ID as deterministic ties. The three-repeat gate's measured mean (45.494 s) is added to its base suite's assignment weight. Execution order inside each shard is retained from the old workflow.

Shard Suites Port Predicted suite + repeat time Special ownership
1 39 13581 505.977 s axe gate
2 58 13582 506.171 s core coverage
3 58 13583 505.983 s three slide-over repeats

These predictions exclude duplicated checkout/build/install/fixture setup, report and upload overhead. Three shards are retained as requested; assignment loads differ by under 0.2 seconds. Go may now dominate total pipeline elapsed time, so E2E improvement must not be presented as equal whole-pipeline improvement.

Full measured suite timing table: seconds in each baseline execution
Suite 38410864651, attempt 1 38410864651, attempt 2 38410864651, attempt 3 Mean seconds Shard
test-node-liveness-e2e.js 2.005 3.123 3.666 2.931 2
test-e2e-playwright.js 102.226 118.828 118.984 113.346 2
test-a11y-axe-1668.js 338.170 425.371 423.635 395.725 1
test-filter-ux-e2e.js 1.872 2.494 2.552 2.306 1
test-channel-issue-1087-e2e.js 2.084 2.738 2.748 2.523 1
test-channel-issue-1111-e2e.js 1.454 1.983 1.989 1.809 2
test-channels-client-state-152-e2e.js 8.786 9.751 9.775 9.437 3
test-channels-154-155-e2e.js 12.169 13.740 13.913 13.274 3
test-map-modal-fluid-e2e.js 5.217 6.144 6.194 5.852 1
test-issue-332-no-carto-tiles-e2e.js 80.243 89.187 90.158 86.529 3
test-map-nodes-pagination-e2e.js 1.165 1.668 1.675 1.503 3
test-issue-123-map-lifecycle-e2e.js 27.094 30.984 31.405 29.828 2
test-observer-iata-1188-e2e.js 3.418 4.688 4.756 4.287 2
test-xss-333-pages-e2e.js 11.445 14.462 14.850 13.586 3
test-xss-392-perf-e2e.js 1.642 2.115 2.106 1.954 2
test-xss-368-home-links-e2e.js 1.548 2.059 2.058 1.888 1
test-xss-429-home-footer-e2e.js 11.592 14.217 14.602 13.470 3
test-issue-1639-observers-sort-e2e.js 4.609 5.810 5.863 5.427 3
test-issue-405-observers-listener-leak-e2e.js 7.694 9.225 9.435 8.785 3
test-issue-1758-ng-filter-rerenders-e2e.js 1.950 2.452 2.445 2.282 2
test-nav-fluid-1055-e2e.js 2.917 3.290 3.458 3.222 2
test-nav-priority-1102-e2e.js 1.537 1.868 1.910 1.772 3
test-nav-priority-1311-e2e.js 2.691 3.238 3.258 3.062 2
test-nav-priority-1391-e2e.js 3.765 4.436 4.433 4.211 3
test-issue-1413-nav-overlap-e2e.js 1.678 2.075 2.075 1.943 2
test-issue-1400-nav-vertical-clip.js 1.359 1.764 1.734 1.619 2
test-nav-more-floor-1139-e2e.js 2.204 2.647 2.661 2.504 3
test-bottom-nav-1061-e2e.js 1.657 2.035 2.086 1.926 3
test-gestures-1062-e2e.js 4.518 5.102 5.184 4.935 3
test-gestures-1185-scroll-discriminator-e2e.js 2.029 2.406 2.422 2.286 3
test-gesture-hints-1065-e2e.js 23.726 25.735 25.990 25.150 3
test-touch-gestures-coverage-e2e.js 14.664 15.463 15.591 15.239 2
test-channel-fluid-e2e.js 5.003 6.415 6.557 5.992 2
test-table-fluid-e2e.js 8.671 10.226 10.415 9.771 2
test-charts-fluid-1058-e2e.js 9.469 11.822 12.100 11.130 3
test-slideover-1056-e2e.js 12.841 15.702 16.327 14.957 3
test-issue-1692-packets-init-parallel-e2e.js 1.172 1.636 1.664 1.491 2
test-issue-147-packets-url-obs-e2e.js 11.652 13.967 14.303 13.307 2
test-issue-165-grouped-hop-warn-e2e.js 5.179 6.572 6.736 6.162 1
test-packet-detail-sender-hash-size-obs-e2e.js 2.324 3.264 3.291 2.960 1
test-issue-353-path-hash-warn-e2e.js 13.948 18.905 18.717 17.190 3
test-issue-96-hide-control-e2e.js 7.105 11.092 10.650 9.616 3
test-issue-242-type-exclusions-e2e.js 4.897 5.844 5.579 5.440 1
test-issue-406-packets-live-channel-e2e.js 4.570 4.999 4.937 4.835 1
test-issue-180-packets-url-modal-e2e.js 16.914 22.457 21.199 20.190 2
test-slideover-1168-munger-e2e.js 3.083 4.466 4.070 3.873 3
test-logo-pulse-1173-e2e.js 3.687 4.942 4.627 4.419 2
test-issue-1122-packets-filter-ux-e2e.js 1.471 2.078 1.981 1.843 2
test-issue-1122-details-row-clamp-e2e.js 3.968 5.832 5.221 5.007 1
test-issue-258-column-widths-e2e.js 22.590 28.130 26.644 25.788 3
test-issue-1128-packets-layout-e2e.js 1.791 2.523 2.302 2.205 1
test-issue-189-group-caret-e2e.js 1.443 2.110 1.957 1.837 3
test-issue-254-affinity-toggle-mobile-aria-e2e.js 6.069 7.984 7.637 7.230 3
test-issue-259-mobile-expanded-group-e2e.js 4.286 5.831 5.617 5.245 1
test-issue-1128-multi-viewport-e2e.js 4.619 6.548 6.291 5.819 2
test-issue-1136-live-region-e2e.js 1.197 1.979 1.871 1.682 3
test-live-multibyte-only-e2e.js 6.273 9.878 9.598 8.583 2
test-issue-125-live-toggles-early-e2e.js 14.006 22.092 21.369 19.156 2
test-issue-220-live-filter-readiness-e2e.js 18.948 25.106 24.627 22.894 2
test-issue-1150-404-state-e2e.js 0.945 1.585 1.526 1.352 1
test-issue-199-inactive-observer-e2e.js 1.061 1.708 1.682 1.484 1
test-issue-1146-path-link-contrast-e2e.js 3.242 5.082 5.014 4.446 3
test-issue-1705-subpath-contrast-e2e.js 0.446 0.761 0.731 0.646 1
test-issue-1147-section-order-e2e.js 1.068 2.156 2.179 1.801 1
test-issue-2073-recent-adverts-e2e.js 6.217 7.546 7.507 7.090 2
test-issue-245-advert-intervals-e2e.js 2.118 3.414 3.339 2.957 1
test-issue-1151-orphan-separators-e2e.js 1.444 2.340 2.205 1.996 1
test-issue-1486-collapse-reopens-detail-e2e.js 2.029 2.714 2.673 2.472 1
test-logo-rebrand-e2e.js 1.750 2.633 2.565 2.316 2
test-logo-theme-e2e.js 1.245 1.998 1.935 1.726 1
test-logo-default-sage-teal-e2e.js 1.703 2.762 2.725 2.397 2
test-issue-1109-hamburger-dropdown-visible-e2e.js 1.259 2.117 2.034 1.803 1
test-live-layout-1178-1179-e2e.js 2.611 3.793 3.773 3.392 3
test-issue-1205-live-controls-anchor-e2e.js 4.099 5.858 5.767 5.241 3
test-live-mql-leak-1180-e2e.js 4.040 4.835 4.964 4.613 1
test-issue-1204-live-panel-structure-e2e.js 4.080 5.714 5.682 5.159 2
test-issue-1234-live-chrome-pass2-e2e.js 2.733 3.861 3.870 3.488 2
test-issue-1206-vcr-overlap-e2e.js 2.591 3.815 3.796 3.401 2
test-issue-1833-legend-toggle-clickable-e2e.js 2.113 2.985 2.995 2.698 1
test-issue-1244-live-vcr-row-hints-e2e.js 4.693 5.864 5.675 5.411 2
test-issue-1510-live-nav-pin-e2e.js 1.389 2.101 2.607 2.032 3
test-live-fullscreen-1572-e2e.js 1.549 2.342 2.293 2.061 1
test-issue-1599-replay-freeze-e2e.js 3.490 4.264 4.278 4.011 2
test-pr-1490-live-map-gpu-animations-e2e.js 3.295 4.610 4.549 4.151 1
test-issue-1648-m1-icons-e2e.js 3.069 4.025 4.003 3.699 2
test-issue-1648-m2-icons-e2e.js 1.412 2.492 2.381 2.095 2
test-issue-1648-m3-icons-e2e.js 3.987 4.597 4.600 4.395 1
test-issue-1648-m4-icons-e2e.js 12.997 13.895 13.843 13.578 2
test-issue-1657-analytics-channels-group-sprites-e2e.js 1.695 2.363 2.347 2.135 1
test-issue-1224-channels-mobile-ux-e2e.js 4.479 8.933 8.909 7.440 2
test-issue-1367-channels-chat-app-e2e.js 2.061 3.019 2.923 2.668 1
test-issue-2052-touch-target-e2e.js 16.273 21.090 20.566 19.310 3
test-touch-targets.js 0.583 0.996 0.976 0.852 2
test-channel-proposals-e2e.js 21.874 20.011 20.240 20.708 3
test-channels-client-state-152-decrypt-e2e.js 7.980 8.644 8.607 8.410 3
test-issue-315-estimated-positions-e2e.js 4.650 6.435 5.963 5.683 3
test-issue-1236-map-mobile-e2e.js 2.425 3.668 3.414 3.169 3
test-issue-1329-map-controls-accordion-e2e.js 2.695 3.842 3.754 3.430 3
test-issue-1273-qr-overlay-height-e2e.js 2.627 3.857 3.842 3.442 1
test-issue-1281-location-row-e2e.js 23.193 26.846 12.898 20.979 2
test-issue-1279-legend-p2-e2e.js 1.765 2.399 2.213 2.126 3
test-issue-1799-label-vocab-e2e.js 2.201 3.148 3.241 2.863 3
test-home-coverage-e2e.js 3.746 5.683 5.547 4.992 2
test-issue-304-my-mesh-e2e.js 1.405 2.130 1.977 1.837 3
test-issue-2027-my-mesh-node-page-e2e.js 6.320 8.694 8.232 7.749 2
test-path-inspector-coverage-e2e.js 1.357 2.149 1.527 1.678 3
test-issue-1206-resize-observer-leak-e2e.js 22.170 35.933 33.321 30.475 2
test-nav-drawer-1064-e2e.js 10.993 14.289 13.017 12.766 2
test-issue-111-drawer-version-e2e.js 9.816 12.367 11.895 11.359 3
test-audio-live-1297-e2e.js 1.232 1.994 1.877 1.701 1
test-audio-lab-1297-e2e.js 1.971 2.875 2.725 2.524 3
test-channel-decrypt-e2e.js 1.028 1.654 1.557 1.413 1
test-channel-qr-e2e.js 1.238 1.950 1.798 1.662 1
test-channel-color-picker-e2e.js 1.358 2.068 1.912 1.779 2
test-customize-theme-e2e.js 3.355 3.468 3.382 3.402 1
test-customize-branding-e2e.js 3.882 4.876 4.667 4.475 1
test-customize-display-e2e.js 3.364 4.261 4.103 3.909 1
test-customize-export-e2e.js 2.274 3.074 3.033 2.794 2
test-drag-manager-e2e.js 3.678 4.977 5.023 4.559 2
test-issue-1567-corner-clears-drag-e2e.js 2.004 2.740 2.782 2.509 2
test-issue-1306-collisions-terminology-e2e.js 15.702 19.864 19.745 18.437 3
test-issue-205-analytics-subtab-deeplinks-e2e.js 9.219 11.902 11.730 10.950 2
test-issue-226-hash-stats-sort-e2e.js 13.119 15.718 15.584 14.807 2
test-issue-236-analytics-sorting-e2e.js 4.004 5.098 5.074 4.725 3
test-issue-1374-route-map-a11y-e2e.js 9.718 10.599 10.103 10.140 3
test-channels-list-render-e2e.js 1.770 2.277 2.221 2.089 2
test-channels-selection-flow-e2e.js 1.323 1.912 1.850 1.695 2
test-channels-add-modal-e2e.js 1.842 2.441 2.390 2.224 3
test-channels-share-color-e2e.js 1.500 2.086 2.032 1.873 1
test-channels-ws-batch-e2e.js 1.186 1.769 1.693 1.549 3
test-channels-ws-race-1498-e2e.js 2.349 3.467 3.414 3.077 3
test-channels-observed-path-hash-size-e2e.js 1.104 1.671 1.647 1.474 2
test-issue-1487-byop-modal-layout-e2e.js 1.282 1.790 1.767 1.613 1
test-issue-1630-reach-mobile-e2e.js 1.610 1.570 2.068 1.749 2
test-node-reach-coverage-e2e.js 0.627 0.834 0.816 0.759 2
test-reach-rank-e2e.js 3.740 5.244 5.129 4.704 2
test-issue-1640-compare-discovery-e2e.js 3.252 4.476 4.305 4.011 3
test-1110-live-filter.js 3.553 5.115 4.909 4.526 3
test-analytics-fluid-charts.js 2.293 2.807 2.771 2.624 2
test-e2e-1267-mobile-vcr.js 5.614 6.440 6.409 6.154 3
test-issue-1274-legend-coverage-e2e.js 2.696 3.668 3.690 3.351 1
test-issue-1648-m5-icons-e2e.js 8.467 9.498 9.479 9.148 2
test-live-dedup.js 6.259 6.882 6.879 6.673 3
test-nodes-export-e2e.js 1.519 2.292 2.234 2.015 3
test-show-neighbors.js 9.062 9.668 9.617 9.449 2
test-a11y-1705-subpath-hop-prefix-e2e.js 0.023 0.034 0.031 0.029 1
test-a11y-1719-contrast-root-causes-e2e.js 0.029 0.041 0.037 0.036 3
test-nodes-favorite-rerender-e2e.js 0.976 1.432 1.337 1.248 3
test-xss-333-e2e.js 0.414 0.647 0.632 0.564 2
test-packet-trace-alignment-e2e.js 0.550 0.804 0.783 0.712 3
test-live-pulse-ring-weight-e2e.js 2.082 2.878 2.756 2.572 3
test-channel-modal-e2e.js 1.277 2.062 1.900 1.746 3
test-node-reach-e2e.js 1.190 1.906 1.804 1.633 2
test-path-inspector-e2e.js 2.497 3.144 2.927 2.856 3
test-issue-1522-trace-url-sync-e2e.js 1.098 1.713 1.626 1.479 3
test-slideover-1056-e2e.js (3 additional repeat-gate executions, aggregate marker span) 36.676 51.375 48.431 45.494 3

All 155 regular suite durations use exact paired START/END log timestamps. The permanent three-repeat gate has one aggregate START/END wrapper; individual repeat durations are not claimed. The repeat weight is bundled with its regular suite for balancing. Predictions exclude shard setup, fixture preparation, teardown/uploads, and coverage-report overhead.

Fixture, coverage and fail-closed behavior

  • One shared YAML steps anchor keeps all three fixtures identical: instrument, freshen, grouped/GRP_DATA SQL, migrate, then 2073/199/245 seeds, local server. Each job has its own checkout/database and distinct pinned localhost port.
  • Every existing command environment, CHROMIUM_REQUIRE setting and output channel is preserved. The five pinned Leaflet assets/hashes used by Feature request: allow operators to disable estimated node positions via configuration #315 are preserved in a helper and included in that suite's measured time.
  • Root E2E discovery rejects missing assignments, duplicates, invalid shard IDs and new browser imports, including files mistakenly added to the unit registry. Only the existing default-off RX suite exclusion remains; bug: MQTT sources panel unreadable at 375px mobile — columns overflow, cells run together Kpa-clawbot/CoreScope#1697 stays a VM unit.
  • Child exit errors/signals fail fast. Parent cancellation remains failure even if the child exits zero after handling TERM/INT.
  • Unique shard artifacts contain logs and per-execution receipts. The report requires current successful shard results, the same manifest/run/SHA, and complete successful suite/repeat execution lists. Valid successful receipts carried over by a failed-jobs rerun are supported; wrong-run/head or future-attempt receipts are rejected.
  • Explicit artifact overwrite handles reruns. Combined badges keep the original counting semantics: node-liveness and extra repeat-gate logs are not added to the ordinary-suite badge count. Coverage collection remains push-only and runs once on the core owner.
  • Exactly 9 guard literals remain in deploy.yml (8 executable plus header comment), and 1 in release-fast-path.yml. Own diff against current master changes no settings, squad workflow, release-fast-path, publishing/deploy condition or production code. Incoming ordinary master merges do include their separately reviewed server changes.

Verification before push

  • Full server suite: PASS; full ingestor suite: PASS.
  • Focused workflow/fork guards under -race: PASS.
  • Historical pre-integration sh test-all.sh: 243 files passed, 0 failed. Later master-merge validation is reported separately below.
  • Mandatory frontend unit suites: PASS, including 713 helper checks.
  • New shard behavioral tests: 9/9 passed; registry: 10/10; all-six gate combinations: PASS.
  • JS/bash syntax and git diff --check: PASS. Actionlint's YAML/Actions check has only the existing custom self-hosted label diagnostic; full ShellCheck output retains pre-existing style diagnostics.
  • Independent immutable-source reviews: helpers, workflow and measured manifest PASS. Reviewer independently reconstructed all 155 commands/environments and LPT assignments from the actual logs.

Red mutants / green controls

Scratch-only mutation runs, never pushed:

  • Ignore shard 2 or 3 in the gate, accept skipped, omit shard/report needs: actual gate test exits 1 on the intended assertion.
  • Remove real test-filter-ux-e2e.js assignment: validator and registry exit 1 with unassigned E2E suite.
  • Add a new runnable but unassigned E2E file: validator and registry exit 1 on its filename.
  • Remove the actual unassigned-suite enforcement: behavioral test exits 1 with missing expected exceptions.
  • Restored controls are green.

Completed post-change PR CI measurements

Run 38425252311, attempt 1 on 4ef231a7, ended failure. Go Build & Test failed in Build and test Go server (with coverage): TestPollerBroadcastsNewData, websocket_test.go:241, expected data.packet.timestamp to exist. The poller, database query and test are unchanged by this PR. There was no race-detector warning.

All three shards and their report passed, with 9m15s E2E/report wall span (shard jobs 8m48s / 8m08s / 8m55s, report 17s). All 158 suite/repeat child executions were verified from the artifacts with exit 0 and the same manifest. Image-check's local Docker build passed. The required gate correctly failed with GO_RESULT=failure, while every shard/report/image result was success; GHCR, release, deploy and badge publishing did not run.

The failed attempt consumed 47m39s actual runner time. This is an incomplete failed-pipeline measurement, not a green before/after cost comparison, and will remain separately disclosed. No Go assertion, timing, retry or skip is changed in this PR.

Attempt 2 of the same pull-request run on 4ef231a7 was a complete SUCCESS, with fresh Go, three shard, report, image and required-gate job IDs. All required jobs passed; release, deployment and publication stayed skipped. The three shard artifacts contain all 158 expected suite/repeat child runs with exit 0 and matching manifest/checkout context.

Measurement Baseline mean, three green executions Sharded attempt 2, one green execution
Full E2E/report wall span 26m33.7s 10m55s
Actual all-job runner minutes 50.64 53.87
Whole execution span 26m56.7s 23m59s
Shard job seconds (1 / 2 / 3) not applicable 639 / 510 / 584

The observed E2E/report span is 58.9% shorter, while actual all-job runner time is 6.36% higher. The after sample is n=1, so it has no repeatability/variance estimate. Whole execution is now mostly Go-bound. Runner minutes sum actual non-skipped job durations, not billed rounded minutes; queue and rerun idle wait are excluded. Baseline 529e008c and after head 4ef231a7 also differ by incoming #422 Go configuration/test changes; this is not a source-identical A/B comparison. Go changes and hosted-runner variability are not attributed to sharding. The three baseline executions are attempts of one baseline run ID, and the successful after execution is attempt 2 of a different run ID. At the latest merge head, the manifest's weights remain historical baseline estimates; #435 adds core browser checks without inventing new timing samples for them.

Attempt 3 used the same unchanged head but shard 3 failed in test-issue-315-estimated-positions-e2e.js, browserChecks:173:16 (caller 277:7): page.click timed out after 10,000 ms waiting for the synthetic missing-GPS node row tr[data-key="3152000000000000000000000000000000000000000000000000000000000000"]. Go, both other shards and image validation passed; the report and required check correctly failed closed. This is the suite body, not fixture preparation or Leaflet download: all five pinned Leaflet checks passed immediately beforehand. The suite starts its own synthetic DB/server/browser context rather than sharing the shard fixture. Its source, fixture and relevant node UI are byte-identical to the master included in that head. The failed execution's E2E/report span was 10m38s, and actual all-job runtime 51m44s; these are failed-execution diagnostic numbers, not a green comparison. All publishing/deployment jobs stayed skipped.

The second complete green measurement at that unchanged head was not obtained. There is no fourth retry of it. Master subsequently advanced to 8665b0c7 (#435), requiring the ordinary merge and fresh validation described below. Fresh pull-request run 38436317680, attempt 1, completed SUCCESS on merge head 045cf701, tree 277f3372: Go, all three shards, receipt/coverage report, image validation and the stable required gate passed. All 158 expected child suite/repeat executions had exit 0 and the same manifest/context. The actual GitHub checkout 103a5705 has exactly that tested tree and parents master 8665b0c7 plus head 045cf701. GHCR login/push, release, deployment and badge publishing stayed skipped.

Successful post-change execution Head E2E/report wall Actual all-job runner minutes Whole execution Shard job seconds (1 / 2 / 3)
38425252311, attempt 2 4ef231a7 10m55s 53.87 23m59s 639 / 510 / 584
38436317680, attempt 1 045cf701 11m19s 56.25 23m34s 602 / 653 / 643
38441232737, attempt 1 514392a7 10m53s 50.43 18m50s 605 / 589 / 636
38446859914, attempt 1 1ec70c20 10m58s 56.20 24m44s 636 / 594 / 591
38452595221, attempt 1 fa84117f 11m28s 56.27 23m31s 623 / 607 / 667

Compared separately with the three-execution baseline mean (26m33.7s E2E, 50.64 actual runner minutes), E2E/report time is 58.9%, 57.4%, 59.0%, 58.7% and 56.8% shorter in these observations. Actual runner time was 6.36% and 11.07% higher in the first two, 0.42% lower at 514392a7, 10.97% higher at 1ec70c20, and 11.10% higher at fa84117f; no causal cost-saving claim is made. Each post head has n=1, and #435 adds core E2E checks, so they are not pooled into an identical-input after mean or variance estimate. Baseline-to-after also includes #422 Go config/test drift; later heads add #431 MQTT/pprof operations, #430 API cache bounds, #426 hardening, #433 WS history, #424 backup, #440/Kpa-clawbot#1692 fixture-window changes and #427 frontend/#165 tests, which may affect runtime. This is not a source-identical A/B experiment, and observed all-job cost or Go-time changes are not attributed solely to sharding. Manifest weights remain historical baseline estimates. Failed attempts 1 and 3 stay separately disclosed and excluded; green results do not fix their independent defects.

During the final read-only check, master advanced again to dd712bc9 (#431 and #430). It is included by ordinary merge 514392a7; fresh PR run 38441232737, attempt 1, completed SUCCESS on that exact head. Go, all three shards, the receipt/coverage report, local Docker-image validation and 🏗️ Build & Publish Docker Image all passed. GHCR login/push, release, staging-deploy and badge publishing were explicitly skipped at job/step level. All 158 ordered suite/repeat child runs had exit 0, no signal and matching manifest hash. Their common GitHub checkout f76c66f0 was independently checked through the GitHub Git API: tree 0ff34246, parents master dd712bc9 and PR head 514392a7, identical to the local tested tree.

Latest E2E/report wall span includes the full shard jobs and report: 10m53s. Actual all-job runner time is 50m26s (50.43 min), not billed rounded minutes. Comparable whole execution, earliest actual job start through last non-skipped job completion, is 18m50s; GitHub's API run-level start/completion span is 18m54s, including three seconds of bootstrap and one second of completion bookkeeping. Queue and rerun idle time are excluded throughout. The three baseline executions are three attempts of one run ID, while the three completed successful sharded executions above are separately identified run IDs/heads.

Post-push local browser verification also passed: Kpa-clawbot#1122 18/18 on each of the three independent local fixture servers, three extra slide-over runs 27/27 each on the owner port, and #406's self-contained Chromium smoke 21/21. All owned processes exited and ports were freed.

Known independent Go-test gap

A separate read-only diagnosis confirmed identical websocket.go, websocket_test.go and db.go on the historical tested master d34b228a and measured head 4ef231a7. An initialization-barrier probe reproduced the missing fallback timestamp 3/3 on both; the representative production packet-store path passed 3/3 on both. The original test passed 25/25 on both by initializing its cursor after the INSERT and then accepting no broadcast. Those passes were vacuous for this assertion. Later incoming WebSocket changes are not covered by this historical source-identity claim.

Production main.go sets poller.store; the legacy nil-store database fallback instead returns first_seen without timestamp. This is an existing fallback-contract/test-ordering defect, not evidence that #434 introduced it. It is not fixed by a green rerun and needs a separate follow-up; no Go production/test behavior is weakened or changed here. This draft is not a merge authorization.

Independent existing navigation/theme vulnerability

A separate reviewer reproduced the exact #315 missing-row timeout on both unchanged master d34b228a and measured candidate 4ef231a7 by forcing theme-refresh to run between list-navigation hash assignment and the router handling it. The node page reselects the old node, rewrites the hash to its full detail and leaves no list row to click. Captured API responses still contained all four synthetic nodes; captured DOM/URL showed full detail instead of the list. An unforced local execution passed all three #315 policy modes. Original suite, fixture and node-UI hashes were unchanged, and owned probe processes exited.

This proves a pre-existing navigation/theme ordering vulnerability, not the actual cause of CI attempt 3: that artifact lacks failure DOM/trace, so a matching forced-order reproduction is not causal proof. No concrete sharding regression was established. The failure remains visible, and this PR does not skip the suite, relax its assertion, raise its timeout or fix unrelated production code. A separate focused fix should prevent cosmetic theme refresh from overwriting pending navigation and add a deterministic regression test.

Scope and master drift

Master d34b228a88bc3b17e6602d3b9d34ad8c453f0a2a was included through ordinary merge commits for the measured head 4ef231a7. The incoming #423 E2E and #422 config changes are preserved. During measurement, master advanced to 8665b0c7603cd4a54a0fceadfd4d44c1a3a5ad6d (#435 packet-count help); it is now included and pushed in ordinary merge commit 045cf701430b128c0b5ef118d87f0b4e5f2d065d, tree 277f337264178877e4274c9488ed053c6bc84ec3. All seven incoming files are inherited byte-identically from master without conflict; all 11 reviewed sharding feature files are unchanged. Fresh local checks passed: all 243 registered JS test files, server package (41.819 s), focused fork guards under -race (1.582 s), syntax/diff checks and exact 9/1 literal fork guards. No rebase or force-push. All feature and merge commits use dborup <kontakt@meshview.dk>.

The exact new merge tree also passed bounded local Chromium validation with the unchanged CI fixture preparation on its own port: core test-e2e-playwright.js exit 0, 151 checks passed and three existing skips (106.7 s), including every incoming packet-count-help check; Kpa-clawbot#1281 exit 0, 6/6 (5.6 s). The initial archive lacked the runtime Git metadata available in CI's checkout, so its Version-card assertion failed; supplying only the exact exported commit via scratch .git-commit resolved that confirmed harness mismatch without changing source, tests or fixtures. Owned servers/browser processes exited and port 13582 was freed. This local macOS pass is supplementary, not a substitute for the fresh Linux PR run.

No staging/production contact, ready marking, PR merge, issue closure or upstream writes. This PR remains draft for a separate merge decision.

Historical master merge 514392a7

Final preflight found master dd712bc92ad916b489be3a9002cc0fefc328f43f, incorporating #431 MQTT/pprof settings and #430 bounded analytics caches. Ordinary merge commit 514392a751c07f78c80c911546a20b6f94de9c87 has parents 045cf701 and dd712bc9 and tree 0ff34246702dc50152813b2cb3019da22abf2ee7. All 35 incoming files match master except the two expected feature overlaps: deploy.yml and test-all.sh preserve both sides' additions. The new internal/pprofbind test line and broker-check unit registration are retained. Diff against this master remains exactly the 11 intended sharding files; the other nine feature blobs are unchanged. Independent immutable-tree audit passed with no findings, unchanged fixtures/aliases/ports/gate and exact 9/1 fork guards.

Fresh local validation at this historical merge: server 43.763 s, ingestor 110.729 s, new pprof module under -race 1.301 s, and all 244 JS unit-test files passed. Server/ingestor/migrate binaries were rebuilt from the exact new tree rather than reusing old production code. The core browser suite passed 151 checks with three existing skips (108.6 s); #315 passed default/enabled/disabled real API and browser policy modes (6.8 s), with the same pinned Leaflet files. Owned processes exited and localhost 13582 was freed. Linux PR CI on 514392a7 completed successfully as detailed above; this is not evidence of CI success on the later 1ec70c20 merge.

Integration with issue #426 hardening

Master advanced to a20c611eafe0711894e2164d5f2a0ad34d450ede after that green execution, including #438 (issue #426 CI hardening), #433 (WebSocket-client history), #424 (backup locking) and #440 (the existing Kpa-clawbot#1692 E2E fixture-window fix). Normal merge 1ec70c20fe52f98e3829d1a1e51e49390e55163d has parents 514392a7 and a20c611e, tree 87544b279349fa6354fcf447a44bb55b0e62382f. No rebase, amend or force push.

The workflow retains #426's local image job contents: read permission and 20-minute timeout. The only conflict was in test-ci-parallel-gates.js; resolution retains both the real six-prerequisite gate cases and the new every-job publishing-surface/permissions/timeout checks. Incoming Go hardening tests and the new Perf WS-client unit registration are also retained. Own diff against that master remains exactly the 11 sharding files. Fresh immutable-tree audit, mutation/control checks, local Go/JS suites and rebuilt local browser validation passed. Automatic PR run 38446859914, attempt 1, completed SUCCESS on exact head 1ec70c20. These incoming server/test changes mean its timings cannot be pooled with earlier heads as identical-input samples.

Local verification on 1ec70c20: server 45.010 s, ingestor 112.576 s, pprof binding module under -race 1.217 s, and both server/ingestor go vet passed. The full JS runner reported 244/245 files green inside the sandbox: the newly inherited backup suite's dead-PID checks failed because the sandbox denied ps -p. That restriction was reproduced directly. The same unmodified suite then passed with normal local process access (95 passed, 0 failed, 50 clearly reported unavailable-host-tool skips), using only mock Docker and disposable files. No source, assertion, skip or retry rule was changed to obtain that result. All 245 registered JS files are therefore covered by the full run plus this explicit environment-corrected backup check, not by a falsely claimed all-green original sandbox run.

Independent audit of exact 1ec70c20 passed: all 17 incoming paths are inherited correctly, with four intentional workflow/test overlaps retaining both sides. Other workflows match master, aliases resolve equally, manifest covers all 155 suites, stable check and six prerequisites remain intact, and fork guards are exactly 9/1. All 25 actual Bash gate cases passed. Ignoring shard 2/3 or accepting skipped results made the gate red; removing an assignment or adding a new unassigned suite made both validator and registry red. Incoming JavaScript and Go publishing/timeout/permissions mutants also turned red. Restored controls passed; 11 focused Go workflow guards passed under -race (1.571 s).

The three native binaries were rebuilt from this exact tree. Its full CI fixture recipe and instrumented local Chromium verification passed: core 151 checks passed / three existing skips (110.9 s), updated Kpa-clawbot#1692 2/2 (1.6 s), Perf WS-client unit 17/17, and unmodified #315 default/enabled/disabled real API/browser checks (6.6 s). Only localhost port 13584 was used; owned browser/server processes exited and the port is free. This supplements the subsequently successful Linux CI run on 1ec70c20.

Run 38446859914 had exactly seven successful jobs and three skipped jobs. Its 158 ordered child runs all exited 0 with no signal and the unchanged manifest. The actual checkout 6a1ffcb224b58028951dc00a4c66f096698babb6 has tree 87544b27 and parents master a20c611e plus head 1ec70c20, verified through GitHub's Git API. E2E/report wall span was 10m58s, actual all-job runner time 56m12s (56.20 min), and comparable actual-job execution span 24m44s. API-level run span was 24m48s, including bootstrap/completion bookkeeping. Go took 24m34s and was the critical path; report took 19s. GHCR login/push, Buildx, QEMU, Docker metadata, release, staging deployment and badge publishing were explicitly skipped. A separate read-only audit reproduced all timestamps, totals and percentages from the raw metadata.

Subsequent #427 master integration

The final ref check then found master c04861bf7f38c78362a854db9b0eabe31197bbb1, incorporating #427's direct-hop/receiver-hint resolution. Required ordinary merge fa84117fb00611c2908fe351f38712e6a1fdb08e has parents 1ec70c20 and c04861bf, tree dc70a36c1773856c9fff06afa0d1838e4807ca27. Incoming scope is six frontend/test files, including the existing #165 grouped-hop E2E; there are no new suite files or workflow/Go changes. All 11 sharding feature blobs are unchanged from the reviewed, green 1ec70c20; assignment weights remain explicitly historical. Fresh local combination checks passed. Before the non-force push, local/remote head, clean worktree, and master were freshly locked and verified. Automatic PR run 38452595221, attempt 1, subsequently completed SUCCESS on exact fa84117f, not merely a historical head. Post-CI refs still match master c04861bf and feature head fa84117f.

Local checks at fa84117f: all 245 registered JS files passed, server 43.677 s, ingestor 109.478 s. Independent immutable audit passed: all six incoming blobs match master, all 11 sharding blobs match 1ec70c20, own scope remains 11 files, guards remain 9/1, manifest covers 155 suites. Fresh gate 25 real Bash cases, shard behavior 9/9, registry 10/10 and 11 focused Go guards under -race passed. Previous red mutants remain applicable because every involved workflow/test/manifest/helper blob is byte-identical, and restored controls were freshly executed.

Fresh native builds and one-pass CI fixture setup also passed in a new immutable archive. Instrumented Chromium ran each suite once: core 151/154 with three existing skips (110.7 s), changed #165 grouped-hop 12/12 (6.2 s), #123 map lifecycle 16/16 (24.2 s), and #315 all three policy/API/browser modes (5.9 s). Actual health commit was fa84117f; port 13585 and all owned processes were clean after exit. Two earlier bootstrap-only attempts executed no tests: sandbox bind/ps restrictions, then duplicate seeding from a reused fixture. Both were stopped and preserved separately; final validation used an entirely fresh source archive/database/public assets and normal localhost/process permission. No suite was retried or weakened.

Completed latest-head CI and acceptance evidence

PR run 38452595221, attempt 1, ended success on head fa84117fb00611c2908fe351f38712e6a1fdb08e: Go, all three shards, verified receipt/coverage report, local image validation and the unchanged required check 🏗️ Build & Publish Docker Image passed. The successful Go/JS unit steps actually ran; the local image build passed. Release, staging deployment and badge publishing stayed skipped, as did Buildx, QEMU, GHCR login, Docker metadata and GHCR push. No staging/production host was contacted.

  • Full E2E/report wall span: 688 s / 11m28s versus baseline mean 1593.667 s / 26m33.7s.
  • Actual all-job runner time: 3376 s / 56m16s / 56.27 min versus baseline mean 50.64 min; these are actual non-skipped job durations, not billed/rounded minutes.
  • Comparable execution span, earliest actual job start to final actual job completion: 1411 s / 23m31s. API-level run span is 1415 s / 23m35s, with three seconds of bootstrap and one of completion bookkeeping.
  • Job seconds: Go 1399; shards 623 / 607 / 667; image 51; report 19; required gate 10. The sum is 3376, and Go is now the critical path.
  • Observed E2E/report reduction is 56.8%; actual runner minutes are 11.10% higher relative to the unrounded baseline mean. Source/head changes and hosted-runner variability prevent causal cost attribution or pooling the five separate post-head observations.

All three artifacts independently verify the 158 exact ordered child executions (155 suites + three extra slide-over repeats), all code 0/no signal, same manifest hash af8c01cc…. Common checkout 4e5a75478a8e2fc845230526339d7cc566649958 has tree dc70a36c1773856c9fff06afa0d1838e4807ca27 and parents master c04861bf plus PR head fa84117f, verified through GitHub's Git API. The offline measurement validator additionally checks each receipt lies inside its owning job's timing bounds, rejects incomplete/failed/stale/empty proofs, and retains separate failed historical diagnostics.

The measured suite table, checked-in manifest, five separately labeled successful PR executions, exact-head green CI and real red-mutant/restored-green gate/unassigned-suite evidence are now complete. Draft and auto-merge-off status are preserved; issue #434 remains open. No ready marking, PR merge, issue closure, force-push, settings change, squad edit, deployment or upstream write was performed.

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.

1 participant