Handoff: UrlResolver PR batch landing + testBytecodeFetch de-flake (#767) + #747↔#749 collision
Written: 2026-07-12 ~21:50 UTC. (Updated snapshot — supersedes the earlier version of this file.)
RE-VERIFY BEFORE ACTING. Every state claim below was true only at write time. PRs merge, CI re-runs,
merge queues shuffle, branches get force-pushed, main advances (bumping the resolver coordinate and
re-conflicting open PRs), and buildtest.kotlin.build goes in and out of reachability. A fresh query
always wins over this document. Authoritative re-checks:
- PRs:
gh pr view <n> --repo CodexCoder21Organization/UrlResolver --json state,mergeStateStatus,statusCheckRollup,headRefOid,mergedAt
- buildtest run:
https://buildtest.kotlin.build/run?id=<id> (HTML only, no JSON API); reachability: curl -sS --max-time 15 -o /dev/null -w '%{http_code}' https://buildtest.kotlin.build/ (000 = down)
- check-runs for a head:
gh api repos/CodexCoder21Organization/UrlResolver/commits/<sha>/check-runs
Mission
Autonomous-loop shepherding of a batch of UrlResolver PRs to green/merge-ready. Mid-session the user
asked, verbatim: "Did you create a PR which fixes the testBytecodeFetch flake?" — expanding the mission
to creating and landing a de-flake PR for testBytecodeFetchAggregatesRelayFailureDetails (now
#767, green), which was the
highest-frequency flake blocking the whole foundation.url:resolver pipeline. The user is now actively
merging the batch. Nothing is merged by the agent without explicit user approval (handoffs excepted);
this doc is NOT authorization to merge code PRs.
Current disposition (write-time, 21:50 UTC — RE-VERIFY)
| PR | Title | State @ write | Head | Note |
|----|-------|--------------|------|------|
| #767 | de-flake testBytecodeFetch | OPEN / CLEAN (green) | ebd92bbf | The de-flake. Fully validated + green. Merge-ready. Branch fix/deflake-bytecode-fetch-aggregates-relay-failure |
| #616 | ByteArray RPC-param marshaling coverage | OPEN / CLEAN (green) | d8e50c10 | Merge-ready. No coordinate bump → doesn't re-conflict |
| #605 | openConnection JSON encoding fix | OPEN / BLOCKED (CI re-running) | 2de3db00 | Re-rebased to pin 0.0.633; CI in progress. Pin treadmill (see below) |
| #747 | retry withdrawals while gossip dial pending | OPEN / DIRTY | b664cf46 | Needs a decision — collides with #749 (see below). Branch fix-registration-withdrawal-resurrection-race |
| #632 | netlab tests for degraded networks | MERGED (17:38 UTC) | d24887ba | Done |
| #595 | netlab relay-reconnection test | OPEN / DRAFT / BEHIND | cf55687e | Deferred; rebase + un-draft after the batch lands |
main @ write time: b3760739 (#653), resolver coordinate 0.0.632.
What was found and done (the chain — verified unless flagged)
testBytecodeFetchAggregatesRelayFailureDetails was a suite-wide flake (VERIFIED). Failed today on
≥4 distinct commits across sessions, ~40–50%/run. From merged #733 (1df283ec). Root cause: the test
rebuilt expected after the fetch by re-reading the live client.getKnownPeers() set and embedding
each relay peer's ${it.multiaddresses}, then exact-assertEquals'd against the exception.message
production built during the fetch. That registry/address set mutates asynchronously (peer exchange /
p2p-circuit reservations), so the two snapshots diverge nondeterministically. Production is correct.
- Fixed via #767 (codex gpt-5.6-sol per the global bug-fix workflow). Branch head
ebd92bbf, 2 commits:
082221f0 core fix (deterministic reproducer: add a late relay peer → old assertion fails 10/10; new
assertion asserts the stable header + full direct-candidate failure + a regex for the full relay reason,
wildcarding only the volatile address list; 20/20 pass); ebd92bbf tightening from an adversarial review
finding (require endsWith("]"), split the relay block into ; -delimited entries, assert the known
relay as one anchored complete entry AND every sibling well-formed; 21/21 + a negative test). Reviews
(codex) approved on substance.
- #767 fix is VALIDATED and now GREEN.
testBytecodeFetch passes on both CI paths. Getting the whole
run green took several rerequests because the suite has other independent flakes (see reusable
knowledge) + fleet degradation (a wedged run stuck at 3/1094 for 31 min, and a buildtest outage
http_code=000). It is CLEAN now.
- #605 rebased repeatedly onto an advancing main. The resolver's own published coordinate lives in
build.kts and every source PR bumps it, so #605 (a source change) re-conflicts on that one line each
time any bumping PR merges: rebased 0.0.626 → 0.0.628 → 0.0.633. Current head 2de3db00, CI re-running.
Each conflict is ONLY the coordinates = "…" line; resolve by keeping main's changelog and setting the
coordinate to main+1. This is a treadmill — on the slow fleet #605's CI takes ~1–2h, during which
main often advances again → DIRTY again. The clean escape is to merge it while green.
- #747 now collides substantively with the just-merged #749 (NEW — the key open item). Main's
0.0.627
is #749 ("registration-after-
withdrawal ordering regression", commit 95e53898), which fixes the same withdrawal-resurrection race
(issue #746) that #747 targets, editing the same src/foundation/url/resolver/UrlResolver.kt. #747 is a
large change there (282 lines, 202+/80−), so rebasing it hits a 6-block source conflict (plus the
build.kts pin). This is a genuine collision between two fixes for the same concurrency race — NOT a
mechanical rebase, and force-resolving it risks reintroducing the race. Left untouched (rebase
aborted; remote branch unchanged at b664cf46). #747's own 4 commits: b664cf46 close-ordering guard +
idle drain, 0d88b23f harden queue admission, d2a821d7 keep withdrawals queued beyond retry budget,
583deb83 fix withdrawal loss during pending gossip dial.
Next steps (ordered — re-verify current state first)
- Re-verify all PRs with the banner command; do not trust the table above.
- #747 — needs a human/owner decision (the single most important open item): Determine how #747 relates
to the now-merged #749. Either (a) reconcile — rebase #747 onto post-#749 main, carefully merging its
additional mechanisms (withdrawal loss during a pending gossip dial, queued-beyond-retry-budget,
queue-admission hardening, close-ordering guard + idle drain) on top of #749's fix, then verify the race
is still fixed (full TDD, delegate to codex gpt-5.6-sol); or (b) reassess scope — check whether #749
already covers enough that #747 should be rescoped/closed. Do the 6-block
UrlResolver.kt conflict
resolution with tests, not by hand-picking hunks.
- Merge decisions (need the user): #767, #616 are green/merge-ready now; #605 when its re-run is green.
Independent PRs (not competing). Do not merge without explicit approval; do not bypass CI / merge
queue (
--admin/--no-verify forbidden). Recommend merging the green ones promptly to end #605's pin
treadmill.
- #605: if it goes DIRTY again before merging, re-rebase (pin → current main coordinate +1) and push
--force-with-lease. If its kotlin.build run wedges (stuck count for >~15 min) or fails on infra
(0 tests / "Waiting for droplet capacity" / shard "BuildTestRunner … is gone"), rerequest.
- #595: rebase onto main + un-draft only after the batch lands.
Reusable / operational knowledge
- Known suite flakes (rerequest, don't "fix" unless doing a real de-flake):
testBytecodeFetch (~45%,
FIXED by #767 — not yet on main until #767 merges, so other open PRs still trip it),
stressTestRegistrationAfterWithdrawalRaceUnderContention (~1–2/32), netlab-hosted tests
(testNetlabPartitionAndHealAcrossNats, testNetlabDynamicFailureRecovery,
testNetlabResolutionUnderLatencyAndPacketLoss — external netlab infra), shard-death crashes,
stressTestConcurrentRegistrationsReliablyPropagateToRelay (exit code 1).
- Re-run a red check w/o a code change: kotlin.build (remote):
gh api --method POST repos/CodexCoder21Organization/UrlResolver/check-runs/<id>/rerequest (id from commits/<sha>/check-runs). bld-build: gh run rerun <run_id> --failed. Confirm both flip to in_progress on the head.
- Infra-failure signatures: shard death = "The BuildTestRunner process on the droplet is gone …"; DO
provisioning = "Failed to create droplet in all regions" + "Waiting for droplet capacity" (0 tests run);
wedged run = completed-count frozen while status=TESTING for >~15 min (rerequest it);
http_code=000 =
CN-relay TLS starvation (wait for recovery, don't churn). Runs can also crawl (coursier resolve on the
CPU-starved CN box) — advancing slowly ≠ wedged.
- build.kts pin-conflict resolution (the #605 treadmill): the conflict is the single
coordinates = "foundation.url:resolver:0.0.NNN" line; keep main's changelog block, append the PR's own
changelog entry renumbered to main+1, set the coordinate to main+1. kompile builds each tests/test*.kts
independently by its own @file:WithArtifact pins, so a test-only PR (#616, #767) does NOT bump the
coordinate and does NOT re-conflict — only source PRs (#605, #747) treadmill.
- codex delegation:
codex exec -C <repo> -m gpt-5.6-sol --dangerously-bypass-approvals-and-sandbox -o <last-msg> "$(cat brief.md)" </dev/null > run.log 2>&1 & — </dev/null is mandatory (stalls otherwise); poll the last-msg file + git log on the branch; nohup/& background job (no auto-notify).
- Local clones:
~/workspace writable (/code/workspace not); gh repo clone (git https has no creds); set git identity on fresh clones.
- Prior handoff PR (merged): https://github.com/CodexCoder21Organization/PlanRepository/pull/1167 (this file supersedes that snapshot).