Repository navigation
quest: plan the route node's creation-order dependence - #8388
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head: 76597e7
No actionable defects found in this planning-only change. Reproducing the early-creation failure before choosing a fix, then proving equivalent routing across creation orders and handle settings, is the right direction. The source confirms that create_route_node builds the feeder cursors from the calling consumer while resetting its routing filters; inherited state remains a hypothesis, not an established cause.
Verification: read the complete quest, the relevant origin construction code, the socket test setup, the related acceptance plan, and #8325's reported regression. Static GitHub review only; I did not run quest context, tests, or independently reproduce the failure.
There was a problem hiding this comment.
ℹ️ Minor suggestions only — plan is factually solid against
main; two small consistency fixes.
Reviewed changes
- New quest
node-creation-order.md— plans making the lite-07 route node and its own-claims feeder independent of which handle or path creates them first, with a reproduce-first Plan and a fix increate_route_node.
Every code reference checks out against main (ecfa75a): route_node at origin.rs:7177, create_route_node at :7189, Producer::with_proxy at :2235, the five route-layer call sites, the socket.rs:307/344/371/392 test lines, the node_id() block at session.rs:271-276 on #8325's head, and the 10772522a5 base (behind_by: 0). The corrections to #8325's field list (stats and interest are reset, not inherited) match the source. No quest in the tree overlaps this one. The m2 placement is a recorded maintainer decision and matches the epic's milestone, so it is not raised.
ℹ️ The routes epic's ## Required list omits the new quest
quest/m2/cluster-routing/routes/README.md:538-544 lists all five existing children with a one-line summary each, and the new quest is the only one missing. The validator does not require the entry (directory membership reaches it either way), but recent quest PRs (#8376, #8379) both added the bullet when adding a child.
Technical details
# Add the new quest to its epic's Required list
## Affected sites
- `quest/m2/cluster-routing/routes/README.md:538-544` — `## Required` lists `availability.md`, `js.md`, `acceptance.md`, `browser-proof.md`, `playwright-pin.md`, but not `node-creation-order.md`.
## Required outcome
- The routes epic lists the new quest like its siblings, so the epic's work list stays complete.
## Suggested approach (optional)
- One bullet opening with the root-absolute link and a one-sentence summary in sibling style, e.g. `- [The route node behaves the same whoever creates it](/quest/m2/cluster-routing/routes/node-creation-order.md) - the lite-07 route node and its own-claims feeder do not depend on which handle creates them first`.ℹ️ The PR body's implementer size contradicts the quest's
The body's Models section says Size: XS while the quest title is # [M] and the body's own Choices say "Sized M". Sibling quest PRs (#8376 M, #8377 S, #8379 XS) all match their title's bracket, so the XS here likely mis-sizes the implementer run for what the doc describes as needing a reproduction and root-cause work first.
Technical details
# Align the Models size with the quest title
## Affected sites
- PR body, `## Models` — `Size: XS`.
- `quest/m2/cluster-routing/routes/node-creation-order.md:1` — `# [M] The route node behaves the same whoever creates it`.
## Required outcome
- The Models section states `Size: M`, matching the quest's title and the body's "Sized M" choice.deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
| node's identity being fixed before the session's own hop or exclusion is | ||
| known. Fix the cause in `create_route_node` so the feeder is built from |
There was a problem hiding this comment.
This candidate cannot be the cause: Consumer::hop is copied from the Producer it was consumed from (rs/moq-net/src/model/origin.rs:7126) and is the origin's configured hop, so every handle on the origin carries the same value, and create_route_node rebuilds horizon from Horizon::default() plus NodeFilter::Own, which discards any exclude a session set. Neither the node's identity nor an exclusion can depend on when the session starts, so the reproduction need not spend time ruling this one out — dropping it (or replacing it with a handle-derived field that actually differs, such as proxy or preference) would keep the list of candidates worth checking.
|
No actionable comments were generated in the recent review. WalkthroughAdded a planning document for the route-node creation-order issue. It describes the reported failures, current lazy-creation paths, candidate causes, and proposed investigation and testing steps. The document records the m2 milestone decision and states that the change does not alter the public API or wire format. Merge Risk:
|

Plans quest/m2/cluster-routing/routes/node-creation-order.md, a follow-up of moq-dev/moq#8325.
Summary
The lite-07 route node, and the feeder that tells it which routes this node serves itself, behave differently depending on which handle or code path creates them first. #8325 found that creating the node at session start makes
room/.server/bobunroutable in threesocket::tests, and worked around it by readingnode_id()without creating the node. This quest finds and fixes the root cause, so creation order stops mattering.Verified against #8325's branch and
main(10772522a5), with corrections to the follow-up as it was reported:route_node()at session start on either branch, and no cluster code sets the route node. feat(net,relay): a lite-07 endpoint declares its own Node ID in SETUP, so a relay refuses a session with itself #8325's SETUP readsnode_id()(lite/session.rs:270-276on its branch) specifically to avoid creating the node. The bug is latent: the node is created lazily by whichever route-layer call comes first (origin.rs:7177, called frompublisher/routed.rs:165,subscriber/routed.rs:120/:799, andpublisher.rs:210/:3792).create_route_node(origin.rs:7189-7230) builds the feeder from the creating handle with..self.clone(). That keeps per-handle fields such asproxy, pool, cache duration, max hops, tasks, and timers. It does not carry a stale node: the node is built fresh from the origin's hop. Whether an inherited field explains the three failing tests is not yet known, so the quest makes reproducing them the first step.Decisions
quest/m2/cluster-routing/routes/(rejected: m1; dropping it). Maintainer, 2026-11-09,/quest-completefollow-up of feat(net,relay): a lite-07 endpoint declares its own Node ID in SETUP, so a relay refuses a session with itself #8325.Choices made without asking
Requiredon feat(net,relay): a lite-07 endpoint declares its own Node ID in SETUP, so a relay refuses a session with itself #8325's quest: this quest reproduces the bug onmainby creating the node early. It does not depend on feat(net,relay): a lite-07 endpoint declares its own Node ID in SETUP, so a relay refuses a session with itself #8325 merging.Impact
Public API: none. Wire: none. Planning only.
Models
Size: XS
Implementer: Claude Code, claude-opus-5-5, medium effort
🤖 Generated with Claude Code
(Written by Claude Opus 5.5 with medium effort)
Review
Rewritten by
quest reviewafter each round.01a1c2a7-ffb0-75d3-8abc-f42ee09755cd, round 1The change only documents a follow-up quest, changes no runtime behavior, and has no actionable defects.