Skip to content

perf(store): in-place resolved-path pubkey scanning - #575

Merged
dborup merged 2 commits into
masterfrom
perf/533-resolved-path-scan
Oct 24, 2026
Merged

dborup merged 2 commits into
masterfrom
perf/533-resolved-path-scan

Conversation

@dborup-agent

Copy link
Copy Markdown
Collaborator

Relates to #533

Summary

decodePersistedRelayPath (Load, chunk merge, live ingest) and the eviction prefetch (resolvedPubkeysForEvictionBatch) decoded every observations.resolved_path value with encoding/json. The ingestor writes that column as compact json.Marshal output of []*string, so this PR reads that form in place and keeps the JSON decoder as the fallback for everything else.

Plan (as executed)

  1. Measure first on master: micro-benchmark of the decoder, eviction-prefetch benchmark, and a 2.5M-observation Load with CPU and memory profiles (the perf(store): evaluate bounded sharing of observer metadata strings #489 synthetic generator, which writes 1–3 full-pubkey hops per row).
  2. Inventory the existing optimisations and where the decoded pubkeys end up.
  3. Tests first (differential, fuzz, grammar, no-pinning, allocation ceilings), shown red against the JSON-only code, then the scanner.
  4. Mutation check, full suites, -race, E2E, before/after benchmarks.

Inventory

  • decodePersistedRelayPath already decoded straight into []string and compacted in place (fix(store): traffic_share_score inflates with uptime — late observations re-append the same tx to byPathHop #158 follow-up), and the live paths call it before taking s.mu. Its contract is extractResolvedPubkeys(unmarshalResolvedPath(s)) plus present (NULL column vs. persisted path).
  • No validation, canonicalisation or case folding happens at decode time. Pubkeys go into byNode / nodeHashes / byPathHop verbatim, so the scanner keeps them verbatim too. Hash width is irrelevant at this layer: hops are full pubkeys or null.
  • The eviction prefetch ran unmarshalResolvedPath (a *string per hop) and then deduplicated per transmission.

What changed

  • resolved_path_scan.go: scanResolvedPathPubkeys accepts only [, then "…" or null separated by ,, then ], where string bytes are printable ASCII (0x20–0x7e) with no backslash. That is exactly the set that json.Unmarshal would return unchanged. Whitespace, escapes, non-ASCII bytes (which JSON would reject or rewrite to U+FFFD), numbers, nested values, top-level null and trailing data all report "not compact", and the caller falls back to the JSON path. Order and duplicates are kept; null and "" are dropped.
  • decodePersistedRelayPath: scans into a stack buffer, then clones each kept hop, because these strings become retained map keys.
  • resolvedPubkeysForEvictionBatch: appends substrings with no allocation, then clones each distinct pubkey per transmission in the existing dedup loop. This matters because evictStale re-assigns s.byNode[pk] = filtered, and assigning to an existing string key stores the new key header. A substring there would pin its whole row (TestEvictionBatchDoesNotPinRows_533 caught this during development).
  • No sharing through the perf(store): evaluate bounded sharing of observer metadata strings #489 pool, and no second pool. Every pubkey the store keeps from these paths is a byNode / nodeHashes / byPathHop map key, and those maps already hold one copy per distinct pubkey. A pool would add a lock and a lookup per hop and save no retained bytes. So there is no new cache, no saturation case, no lock, and no change to trackedBytes charges.

Benchmarks (Apple M5, Go 1.26.3; base = origin/master 273c216, same benchmark file copied in)

Micro, -count 6, medians:

Benchmark base new Δ
DecodePersistedRelayPath_533 (realistic 1–3 hop values) 567 ns, 506 B, 7 allocs 78 ns, 159 B, 2 allocs¹ −86 % time, −69 % bytes
EvictionBatch_533 (10K tx ≈ 150K rows) 239 ms, 217.4 MB, 3.81M allocs 133 ms, 131.0 MB, 2.04M allocs −44 % time, −40 % bytes, −46 % allocs
Load_Obs489 (250K obs, -benchtime 3x) 1351 ms, 608.5 MB, 14.05M allocs 1208 ms, 521.7 MB, 12.80M allocs −11 % time, −14 % bytes, −9 % allocs
Load_Obs489 heapMiB / trackedMiB 134.4 / 133.7 134.4 / 133.7 unchanged

¹ -benchmem truncates to an integer. The mean is just under 3 (one slice plus one copy per kept hop).

Macro, TestResolvedPathScan533_Measure at 2.5M observations / 121,166 transmissions, 3 alternating runs per side:

Metric base new Δ
Load wall 21.53 / 21.53 / 21.30 s 20.52 / 20.21 / 20.33 s ≈ −5 %
Load allocations 140.44M 127.94M −8.9 %
Load allocated bytes 5958 MiB 5131 MiB −13.9 %
Retained heap after load + GC 1246.6–1247.1 MiB 1246.8–1247.3 MiB unchanged (no pinning)
Go Sys after load (peak-RSS proxy) 3573 / 3577 / 3495 MiB 3422 / 3407 / 3447 MiB ≈ −4 %
Eviction prefetch over all tx: wall 2.95 / 2.99 / 2.91 s 1.65 / 1.63 / 1.71 s ≈ −44 %
Eviction prefetch allocations 46.35M 24.84M −46 %
Eviction prefetch allocated bytes 2523 MiB 1522 MiB −40 %

Attribution before the change (pprof on the 2.5M run): the decoder was 4.6 % of Load CPU but 21 % of Load's allocated bytes (17 % of objects). JSON decoding was 48 % of the eviction prefetch's bytes (59 % of objects). The rest of the prefetch is SQL row scanning. These are synthetic measurements on a laptop, not measurements of a deployed instance. Sys is the Go runtime's figure, not OS max-RSS.

Perf justification (hot path): the scan is O(len(value)) per observation with no locks, maps or global state. It runs where the JSON decode ran: outside s.mu on the live paths, and in the unlocked phase of RunEviction.

Tests

  • TestDecodePersistedRelayPathMatchesJSON_533: about 60 edge cases (empty, null, [], nulls, "", duplicates, odd but valid strings, malformed/trailing/whitespace, numbers, nested values, every escape kind, control bytes, DEL, valid UTF-8, invalid bytes, surrogates). Each is checked against extractResolvedPubkeys(unmarshalResolvedPath) for both entry points.
  • FuzzPersistedRelayPath_533: the same differential. Run locally for 120 s, about 4.06M executions, no divergence.
  • TestScanResolvedPathPubkeysGrammar_533: accepts and rejects the right inputs, and leaves dst untouched on reject.
  • TestDecodePersistedRelayPathDoesNotPinInput_533 and TestEvictionBatchDoesNotPinRows_533: retained strings are copies.
  • TestPersistedRelayPathAllocs_533: at most 3 allocs for a 2-hop decode, 0 for the eviction append. On the JSON-only code this was 9 and 11 (red).
  • TestEvictionBatchMatchesJSON_533: compact and fallback rows mixed per transmission, first-seen dedup order.
  • Mutation: 12 hand mutants (grammar holes, missing clone, fallback removed, present lost, dedup removed, scan disabled). All 12 were killed.
  • cd cmd/server && go test ./... ✅, cd cmd/ingestor && go test ./... ✅, go test -race on load/chunk/evict/fix(store): traffic_share_score inflates with uptime — late observations re-append the same tx to byPathHop #158/perf(store): evaluate in-place resolved-path pubkey scanning and bounded sharing #533/TestNoSQLUnderStoreLock ✅, sh test-all.sh 267/267 ✅, node test-frontend-helpers.js 719/0 ✅. test-e2e-playwright.js against a local server on the prepared e2e-fixture.db (CI steps): 154/157, 3 built-in skips ✅.

Scope and invariants

  • No schema, API, config or deployment change. cmd/server remains read-only. No new map[string]interface{}. No frontend change, and check-xss-sinks.sh --diff origin/master is clean. Workflows are untouched.

🤖 Generated with Claude Code

decodePersistedRelayPath (Load, chunk merge, live ingest) and the
eviction prefetch decoded every observations.resolved_path value with
encoding/json. The ingestor writes it as compact json.Marshal output of
[]*string, so read that form directly and keep the JSON decoder as the
fallback for anything else (whitespace, escapes, non-ASCII, non-string
values, trailing data). The result is unchanged: strings verbatim, same
order, duplicates kept, null and "" dropped (differential + fuzz test
against extractResolvedPubkeys(unmarshalResolvedPath)).

Retained pubkeys are copies, never substrings of the row: the load path
clones each kept hop, and the eviction prefetch clones each distinct
pubkey per transmission, since evictStale re-assigns s.byNode[pk] and a
string-key assignment stores the new key.

2.5M observations / 121K transmissions: Load allocations 140.4M -> 127.9M,
allocated 5958 -> 5131 MiB, retained heap unchanged; full eviction
prefetch 2.95 s -> 1.67 s, 46.4M -> 24.8M allocations.

Relates to #533

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dborup-agent

Copy link
Copy Markdown
Collaborator Author

Rapport — CS-MacBook PR#575 #533 — head 5199a44

Status: Implemented and measured, draft. CI is green except E2E shard 3/3, which failed once in test-issue-497-rx-airtime-e2e.js (a frontend CSS-wrap assertion on mocked data). This is not #271, so the job was not re-run. The two gate jobs fail only because of that shard.

Evidence tags: [T] = test/benchmark run locally or in CI, [A] = architecture/code reading, [K] = known or pre-existing, not caused by this PR.

Requirements

# Requirement Evidence Test (red before → green after) Mutant(s) killed
1 Measure first: CPU and allocations on load and eviction at ~150K tx / 2.5M obs [T] master 273c216, 2.5M obs / 121,166 tx. Load: 21.6 s, 140.4M allocs, 5958 MiB. pprof: the decoder was 4.6 % of Load CPU, 21 % of Load bytes, 17 % of Load objects. Eviction prefetch over all tx: 2.95 s, 46.4M allocs. JSON was 48 % of its bytes and 59 % of its objects TestResolvedPathScan533_Measure, BenchmarkDecodePersistedRelayPath_533, BenchmarkEvictionBatch_533, BenchmarkLoad_Obs489 (all compile on master) n/a (measurement)
2 Inventory of the existing decodePersistedRelayPath optimisations [A] It already decoded into []string with in-place compaction, outside s.mu (#158). No validation or canonicalisation at decode time; pubkeys go verbatim into the byNode/nodeHashes/byPathHop keys. The eviction path went through unmarshalResolvedPath and then per-tx dedup covered by the differential tests n/a
3 In-place scanning on the load path with a correctness-preserving JSON fallback [T] differential over ~60 edge cases plus fuzz: 120 s, ~4.06M executions, 0 divergence TestDecodePersistedRelayPathMatchesJSON_533, FuzzPersistedRelayPath_533, TestScanResolvedPathPubkeysGrammar_533 (red: the scanner rejected valid compact input) M1 accept \, M2 accept bytes >0x7e, M3 trailing comma, M4 keep "", M5 non-[ start, M7 present lost
4 In-place scanning on the eviction path with fallback, dedup order preserved [T] TestEvictionBatchMatchesJSON_533 M9 no fallback, M11 dedup removed
5 No pinning of input buffers [T] Retained heap after a 2.5M load is unchanged (1246.6–1247.1 → 1246.8–1247.3 MiB). [A] The eviction re-assigns s.byNode[pk], and a string-key assignment stores the new key, so the batch clones each distinct pubkey TestDecodePersistedRelayPathDoesNotPinInput_533, TestEvictionBatchDoesNotPinRows_533 (red on the substring version) M6 load path without clone, M12 eviction without clone
6 The allocation gain is actually achieved [T] TestPersistedRelayPathAllocs_533 (red: 9 and 11 allocs on the JSON-only code; green: ≤3 and 0) M8 load always JSON, M10 eviction always JSON
7 Reuse the #489 pool if sharing makes sense; no second pool [A] Not used. Every retained pubkey is a map key that already exists once per distinct value, so a pool would cost a lock and a lookup per hop and save 0 retained bytes. No new pool, cache or lock; trackedBytes is unchanged (Load_Obs489 trackedMiB 133.7 → 133.7) BenchmarkLoad_Obs489 heap/tracked metrics n/a (design decision)
8 Ordering, duplicates, hash width, validation preserved [T] Order and duplicates are covered by the differential cases. [A] Hops are full pubkeys or null; there is no hash-width or validation step at this layer, before or after the tests in rows 3 and 4 M3, M4, M11
9 -race, TestNoSQLUnderStoreLock [T] go test -race on `_533 TestNoSQLUnderStoreLock 158
10 Benchmark before/after in the PR description [T] decode 567 → 78 ns, 506 → 159 B. 2.5M Load: allocs −8.9 %, bytes −13.9 %, wall ≈ −5 %. Full eviction prefetch: −44 % wall, −46 % allocs. Load_Obs489: −11 % time see the PR description n/a
11 Recommend closing if the gain is negligible [T] Not negligible on allocations: Load −12.5M allocs, −827 MiB churn; eviction −21.5M allocs per full pass. The CPU gain on Load is modest (≈5 %) n/a n/a

All mutants: 12/12 killed [T].

Invariants

Check Result
cmd/server read-only [A] Only read paths changed; no new SQL. TestNoSQLUnderStoreLock passes [T]
No new map[string]interface{} [T] 0 in the diff
No hardcoded colours, check-xss-sinks.sh --diff origin/master [T] clean (no public/ changes)
Fork guards (9 in deploy.yml, 1 in release-fast-path.yml) [T] .github/ untouched, counts 9 / 1
No schema/API/config/deployment change [A]

Local suites

Suite Result
cmd/server go test ./... [T] ok
cmd/ingestor go test ./... [T] ok
sh test-all.sh [T] 267/267 files
node test-frontend-helpers.js [T] 719 passed, 0 failed
test-e2e-playwright.js (local Go server, fixture prepared as in CI) [T] 154/157, 3 built-in skips
test-issue-497-rx-airtime-e2e.js (local, same server) [T] passed 3/3 runs

CI per job (head 5199a44)

Job Result
Go Build & Test ✅
Go Server Tests 1/3, 2/3, 3/3 ✅ ✅ ✅
Go Ingestor Tests ✅
Go Libraries & CLI ✅
JavaScript Unit Tests & Lint ✅
Script & Container Unit Checks ✅
Verify Go Test Assignments ✅
Validate Docker Image ✅
Playwright E2E 1/3, 2/3 ✅ ✅
Playwright E2E 3/3 ❌ test-issue-497-rx-airtime-e2e.js: "a very narrow tile wraps between stats", nowrap:false on one stat span
Verify E2E Shards & Coverage, Build & Publish Docker Image ❌ gates only (E2E_3_RESULT: failure)
Publish Badges, Release Artifacts, Deploy Staging skipped

Leftovers

@dborup-agent

Copy link
Copy Markdown
Collaborator Author

Review — CS-pve-agent3 PR#575 — head a26c43e

Dom: APPROVE with nits

Independent, read-only review. Head a26c43e0 already contains origin/master 762f706c (merge-base = master), so git merge-tree --write-tree origin/master a26c43e0 (418f5cda) is identical to the head tree. All local runs used git archive extracts in a scratch directory. git ls-remote showed head a26c43e0 both before and after the review.

Evidence tags: [T] = I ran it, [A] = code/architecture reading, [K] = known or pre-existing, not caused by this PR.

Findings

# Severity Finding Evidence
1 Nit (description) The benchmark numbers in the PR description were taken on Go 1.26.3. The project builds and tests with Go 1.27.1 (Dockerfile, Dockerfile.go, CI setup-go). Go 1.27's encoding/json is already cheaper, so the gain on the shipped toolchain is smaller than described, especially on Load (see the table below). The code is still worth it, but please replace the numbers with 1.27.1 figures. The same applies to the comment in TestPersistedRelayPathAllocs_533 ("The JSON decoder costs 7 allocations"): on 1.27.1 the JSON-only code gives 5 and 7 allocs, not 9 and 11. [T]
2 Nit (test gap) Mutant Mc2 survives both the PR's tests and my own differential: replace every return dst[:start], false with return dst, false. Callers are not affected, because appendPersistedRelayPubkeys falls back with its own dst and decodePersistedRelayPath discards buf on failure. However, the documented contract of scanResolvedPathPubkeys ("returns dst unchanged … when s is not in the compact form") is only tested on inputs that are rejected before any pubkey is appended. Adding a reject case such as ["ab",1] or ["ab"x] to the TestScanResolvedPathPubkeysGrammar_533 reject list would kill it. [T]
3 Info In resolvedPubkeysForEvictionBatch, the dedup reuses pks[:0]. The tail beyond len(deduped) still holds substrings of dropped duplicates, which keep their row strings alive until rpBatch is released at the end of RunEviction. This is transient only, and of the same order as the old code, whose tail held separate 64-byte strings. Nothing is retained past the eviction pass, because the map keys come from the cloned values. No action needed. [A]
4 Info The byte-level fuzzer rarely produces long, well-formed compact arrays. My structured generator below covers that region. Adding a few structured seeds (json.Marshal of random []*string) is optional. [T]

No blocking findings.

Answers to the review points

In-place scan equivalent to the JSON decoder (#533)

  • [A] The grammar is closed and conservative: [, then "…" or null separated by ,, then ]. Strings may contain only 0x20–0x7e with no \. Anything else returns false and goes to the unchanged JSON path. I checked the bounds by hand: s[n-1]==']' guarantees that neither a string nor null can consume the closing bracket, and i+1 >= n-1 rejects a trailing comma. Mutant Md, which removes the ] check, panics with index out of range, so the guard is load-bearing and tested.
  • [T] I ran FuzzPersistedRelayPath_533 for 180 s, about 1.28M execs, 477 corpus entries, 0 divergence (-parallel 2).
  • [T] My own structured differential, kept in scratch and not committed: 400K inputs. They are json.Marshal of random []*string with escapes, control bytes, DEL, high bytes, UTF-8, U+2028, <>& and embedded [],"null"; hand-built unescaped arrays; and 1–3 byte mutations of marshalled values. 46K of them took the in-place path. Both entry points were compared with extractResolvedPubkeys(unmarshalResolvedPath(s)), with a non-empty dst prefix for the append form. Result: 0 divergence.
  • [T] All 399 non-NULL resolved_path values in e2e-fixture.db take the in-place path and match the oracle.

Validation, canonicalisation, hash width, ordering, duplicates

  • [A] Before and after alike, no validation or case folding happens at this layer, and pubkeys go into the indexes verbatim. [T] The uppercase pk533B case confirms this.
  • [A] Hash width does not apply here: hops are full pubkeys or null.
  • [T] Order and duplicates are preserved (differential tests). The eviction path keeps first-seen dedup order (TestEvictionBatchMatchesJSON_533).

Safe fallback for escaped or unusual JSON

  • [T] Escapes, whitespace, numbers, nested values, top-level null, trailing data and non-ASCII bytes all fall back. present semantics are unchanged: "" gives not present, corrupt input gives present with no hops.

No pinning of large input buffers

  • [A][T] The load path clones each kept hop. Mutant Mg (no clone) is killed by TestDecodePersistedRelayPathDoesNotPinInput_533.
  • The eviction path clones each distinct pubkey. Mutant Mf is killed by TestEvictionBatchDoesNotPinRows_533.
  • [A] I confirmed that the clone in eviction is necessary: the Go runtime updates a string map key on assignment to an existing key (needkeyupdate is true for strings), so s.byNode[pk] = filtered would otherwise store the substring.
  • [A] buf [8]string stays on the stack: -gcflags=-m shows no "moved to heap: buf".

Measurement, and whether the gain justifies the complexity

  • [T] My before/after on Go 1.27.1, 4 vCPU (wall times are noisy; allocation counts are deterministic):

    Benchmark base 762f706c head a26c43e0 Δ
    DecodePersistedRelayPath_533 (-count 4) ≈465 ns, 236 B, 4 allocs ≈163 ns, 159 B, 2 allocs −65 % time, −33 % B, −50 % allocs
    EvictionBatch_533 (10K tx, -count 4) 398–594 ms, 161.8 MB, 3.016M allocs 294–335 ms, 131.0 MB, 2.037M allocs ≈ −30 % time, −19 % B, −32 % allocs
    Load_Obs489 (250K obs, -benchtime 3x -count 3) 2.75–2.78 s, 521.0 MB, 13.057M allocs 2.62–2.70 s, 501.7 MB, 12.766M allocs ≈ −3 % time, −3.7 % B, −2.2 % allocs
    Load_Obs489 heapMiB / trackedMiB 125.6 / 123.4 125.6 / 123.4 unchanged
  • Verdict: the Load gain is marginal on 1.27.1. The eviction prefetch gain is real; it runs every tick, off-lock. The added code is about 90 lines with a closed grammar, an unchanged fallback, and a strong differential, fuzz and mutation net, so the risk is low. I consider it justified, mainly by the eviction path. See finding 1 for the description.

#489 pool reused, not duplicated

  • [A] No new pool, cache or lock. The pubkeys from these paths end up only as map keys of nodeTxIDs, byNode and byPathHop (indexByNodeKey, addResolvedPubkeysToPathHopIndex). resolvedPubkeyIndex stores hashes only. fallbackByNode holds strings, but from the path_json fallback, not from this path. So there is no retained duplication that obsStringPool could remove. I agree with not using it. trackedBytes charges are unchanged ([T] trackedMiB is identical).

#495 lock rule and -race

  • [A] The live paths still decode before s.mu (store.go IngestNewFromDB/IngestNewObservations: "outside s.mu"). The eviction prefetch stays in the unlocked phase 2 of RunEviction. No new locking.
  • [T] TestNoSQLUnderStoreLock and TestNoSQLUnderStoreLockDetects: PASS.
  • [T] go test -race -run '_533|TestNoSQLUnderStoreLock|158|Evict|Chunk|Load|TrackedBytes|_534|_573|_490|_555|ShareGrowth|489': ok (471 s).

Combination with #534/#573 and #490/#555 after the sync

  • [T] The merged tree is identical to the head tree. The full cmd/server suite is green.
  • [T] TestTrackedBytes_* (9 PASS, 1 measurement SKIP), _534/_573/_490/_555/489 under -race: green.

Invariants

Check Result
No behaviour change beyond the goal [T] differential + fuzz + fixture; [A] only decodePersistedRelayPath and the eviction prefetch change
cmd/server read-only [A] no new SQL; the eviction query is the existing SELECT
No new map[string]interface{} [T] 0 added lines
No hardcoded colours / check-xss-sinks.sh --diff origin/master [T] no public/ changes; script: "no public/**/*.{js,html} changes to scan", exit 0
Fork guards [T] .github/ untouched; 9 in deploy.yml, 1 in release-fast-path.yml (same as master)
Closing keywords [T] none in the PR body ("Relates to #533") or the commit messages
Commit author [T] both commits are dborup <kontakt@meshview.dk>
No schema/API/config/deployment change [T] diff is 5 files under cmd/server/

Acceptance criteria → tests

Criterion (#533) Test Red before → green after
Scanner vs decoder: malformed/escaped, nulls, empty keys, mixed, randomized TestDecodePersistedRelayPathMatchesJSON_533, FuzzPersistedRelayPath_533, TestEvictionBatchMatchesJSON_533 These are equivalence guards against the old decoder, so they are green on the JSON-only code by construction. Their teeth are shown by the mutants (Ma, Mb, Md killed). [T]
The in-place path is actually used (alloc gain) TestScanResolvedPathPubkeysGrammar_533, TestPersistedRelayPathAllocs_533 [T] red with the scanner disabled (5 / 7 allocs, grammar fails), green on head
No pinning …DoesNotPinInput_533, …DoesNotPinRows_533 [T] red on mutants Mg / Mf, green on head
Race + affected load/merge/eviction tests existing suites [T] green
Before/after benchmarks *_533 benches, Load_Obs489, TestResolvedPathScan533_Measure [T] micro and Load re-measured on 1.27.1 (table above)

Tests and mutants I ran

  • [T] cmd/server go test ./...: ok (79 s). cmd/ingestor go test ./...: ok (233 s).

  • [T] sh test-all.sh: 268/268 files passed. node test-frontend-helpers.js: 719 passed, 0 failed.

  • [T] E2E against a local Go server on e2e-fixture.db, prepared as in CI: freshen, the Packets page collapse button in the left column of the table opens the dialog. Kpa-clawbot/CoreScope#1486/"Group Data" message type missing from packet view window's "message type" filter Kpa-clawbot/CoreScope#1791 seed SQL from deploy.yml, corescope-migrate, then seeds 2073, 199, 245 and 122. Results:

    • test-e2e-playwright.js: 154/157, 3 built-in skips
    • test-issue-497-rx-airtime-e2e.js: pass (this is the file that failed on the earlier head 5199a443)
    • test-e2e-532-route-hop-count.js: pass
    • test-path-inspector-e2e.js: 7/0
    • test-issue-76-heard-by-e2e.js: 8/0
    • test-node-liveness-e2e.js: 35 checks passed
    • test-issue-165-grouped-hop-warn-e2e.js: 12/0
    • test-node-reach-coverage-e2e.js: SKIP (clientRxCoverage disabled in the default config)

    The server was stopped by port lookup (fuser).

  • [T] CI run 40121931276 on a26c43e0, per job: Go Build & Test ✅, Go Server 1/3 ✅, 2/3 ✅, 3/3 ✅, Go Ingestor ✅, Go Libraries & CLI ✅, JS Unit & Lint ✅, Script & Container ✅, Verify Go Test Assignments ✅, Validate Docker Image ✅, Playwright E2E 1/3 ✅, 2/3 ✅, 3/3 ✅, Verify E2E Shards & Coverage ✅, Build & Publish Docker Image ✅. Publish Badges, Release Artifacts and Deploy Staging were skipped, as expected for a PR. The known flakes flaky: #226 Hash Stats adopters sort E2E — server sorts multiByteNodes on packets only, ties come out in random order #256 and flaky: TestResolvedPathBackfill_WriteHoldUnderBudget_188 — wall-clock write-hold budget fails under CI load #267 did not occur.

  • [T] Mutants of my own, beyond the author's 12:

    Mutant Change Result
    Ma accept control bytes (c < 0x20 removed) killed (MatchesJSON, Grammar, Fuzz seeds, my differential)
    Mb lax null (any n + 4) killed (panic / MatchesJSON, my differential)
    Mc / Mc2 keep partial dst on reject survives (no caller-visible effect, see finding 2)
    Md drop the s[n-1]==']' check killed (index-out-of-range panic, MatchesJSON)
    Me null advances 3 bytes killed (Allocs, Grammar); my differential misses it because the fallback hides it
    Mf eviction dedup without clone killed (TestEvictionBatchDoesNotPinRows_533)
    Mg load path keeps substrings killed (TestDecodePersistedRelayPathDoesNotPinInput_533)
    JSON-only scanner always returns false red: Allocs (5 / 7) + Grammar

Not verified

  • The 2.5M-observation macro run (TestResolvedPathScan533_Measure), OS peak RSS and retained heap at that scale. The review machine has too little RAM, so I re-measured only the micro benchmarks and Load_Obs489 at 250K.
  • E2E ran against the plain public/, not public-instrumented, and covered only the eight files above locally. The full shard set is covered by CI.
  • No browser or visual check (no frontend change), and no deployed instance was measured.

🤖 Generated with Claude Code

@dborup
dborup marked this pull request as ready for review October 24, 2026 19:28
@dborup
dborup merged commit a38d682 into master Oct 24, 2026
18 checks passed
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