Skip to content

Merge main into dev - #4428

Merged
kixelated merged 89 commits into
devfrom
claude/merge-main-into-dev-e713c30
Sep 29, 2026
Merged

kixelated merged 89 commits into
devfrom
claude/merge-main-into-dev-e713c30

Conversation

@kixelated

@kixelated kixelated commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Merges main (through #4387, e713c30) into dev. dev keeps its breaking changes; main's fixes and features are carried onto them.

Notable conflict resolutions:

Left for a follow-up:

Public API / wire impact: none beyond what the merged main and dev PRs already carry.

Added after review:

  • Merged dev again for fix: bump qmux to 0.6.1 so ws:// keeps the close code #4398 (qmux 0.6.1), which fixes the moq-tokio close_code failures.
  • js/net track cache: with unlimited retention, a sink closed by the producer drops its mirror tracking instead of pinning it forever (main kept it for age-out; dev's optional retention never ages out). Codex finding.
  • test/max-age: the JS subscriber waits for the age start instead of the first announce event, which can be dev's live marker before the relay learns the route (it raced into Unroutable).

Checks: nix develop --command just check origin/dev, just test max-age, and the js/net suite pass locally.

Merge with a merge commit, not squash.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 30 commits September 26, 2026 17:03
…tanding route (#4232)

Co-authored-by: GPT-6 <noreply@openai.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: moq-bot[bot] <186640430+moq-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#4300)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…stroyed (#4290)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…4299)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…4272)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ounce doc (#4305)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…4278)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…et (#4254)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: GPT-6 <noreply@openai.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…anicking (#4302)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
kixelated and others added 10 commits September 28, 2026 14:59
…4407)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…'s path (#4406)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: GPT-6 <noreply@openai.com>
…clients (#4411)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…4405)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Carries main (through #4387) onto dev's breaking changes: #4350 and
#4372 ported into rs/moq-c, main's auth fixes onto the moq-auth lease,
and main's announce and track-cache changes onto dev's event and
optional-retention APIs. Quests deleted on either side stay deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T02:32:19.308326Z 3d0b72a New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Recommendation: MERGE

Head: cdeed8f0c6761302ca3be69f8741b1d90a0d3a8b (main through #4387 → dev)

Branch sync assessment

This is an appropriate main → dev sync: GitHub reports MERGEABLE (no unresolved conflicts), the tip is a real two-parent merge commit (dev + e713c309), and the body documents conflict wins clearly. Direction is right — carry main's fixes/features onto dev's breaking changes rather than the reverse.

What changed (categories; ~666 files, +16.7k / −7.7k, 86 commits)

Spot-checks on the head match the claimed resolutions (cpp_compat: true + no .pc write in rs/moq-c/build.rs; validate_times with exp <= now / nbf > now in moq-auth; Cargo workspace pins as described).

Complexity / alternatives

Worth it: a documented merge-with-conflict-resolution is the right tool for divergent main/dev. Squashing would destroy history and is correctly ruled out. Waiting longer only accumulates more conflicts.

Caveats (do not block the sync itself)

  1. Wait for CI — Check/Test/Interop/Platform/etc. were still pending at review time; merge only once required checks are green.
  2. Known pre-existing moq-tokio close_code failure on dev; fix: bump qmux to 0.6.1 so ws:// keeps the close code #4398 (qmux 0.6.1) is the fix and is intentionally out of scope — land that as a follow-up if CI surfaces it.
  3. Merge with a merge commit, not squash, as the PR and CONTRIBUTING ask.

Verdict: MERGE once CI is green (merge commit).

This is an automated review, not the maintainer's decision
(Written by Grok)

@kixelated
kixelated enabled auto-merge September 29, 2026 00:40

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cdeed8f0c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread js/net/src/track.ts
Comment on lines +575 to +577
if (this.#state.closed.peek() !== undefined) {
dispose();
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Release closed sinks when retention is unlimited

When Info.maxAge is omitted, #prune() intentionally never evicts cached groups. If the producer then closes, this branch disposes the only cleanup listener before removing the sink from each cached entry's mirrors map, so the cache permanently retains that sink and all of its mirrored groups. Ended tracks with unlimited retention therefore accumulate memory for every current subscriber, and late subscribers have the same lifetime problem; detach closed sinks from the cache without discarding the source groups.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on the close path: main's early return (keep mirrors tracked so they age out) meets dev's optional retention (nothing ages out). Fixed in ad8e3c0: with unlimited retention, a sink closed by the producer drops its mirror tracking and leaves the mirrors to its reader.

The late-subscriber half (a sink added after the track closed never registers a close listener) already exists on dev and isn't from this merge, so I'm leaving it for a follow-up rather than widening the sync.

(Written by Claude Opus 5.5)

kixelated and others added 2 commits September 28, 2026 18:27
Main keeps a sink's mirrors tracked after the producer closes so they age
out with the cache. Dev's optional retention never ages anything out, so
drop the tracking there and leave the mirrors to their reader.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad8e3c0a76

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread js/net/src/track.ts
Comment on lines +576 to +579
if (this.#state.closed.peek() !== undefined) {
if (this.#state.info.peek()?.maxAge === undefined) {
for (const entry of this.#cache) entry.mirrors.delete(sink);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detach mirrors for subscribers created after closure

When subscribe() is called after an unlimited-retention producer has already closed, the outer if (closed === undefined) is skipped, so this cleanup callback is never installed; #addSink still mirrors every cached entry into the new sink and immediately closes it, leaving each forever-retained entry.mirrors map holding that sink and its mirrored group indefinitely. The fresh evidence in this revision is that the cleanup added for the prior finding exists only inside the live-sink callback, so late subscribers still leak once per cached group.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path (a sink added after the track closed never registers a close listener) is the same on dev before this merge, so it isn't a merge interaction. Keeping the sync focused and leaving it for a follow-up on dev.

(Written by Claude Opus 5.5)

… event

Dev's announce stream can yield `live` before the relay has learned the
publisher's route, so the JS subscriber raced a subscribe into Unroutable.
Wait for the `age` start, as the Rust arm already does.

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

Copy link
Copy Markdown
Collaborator Author

Merge summary:

  • Test failed on moq-tokio close_code, which also broke dev; fix: bump qmux to 0.6.1 so ws:// keeps the close code #4398 (qmux 0.6.1) had already fixed it there, so dev is merged in.
  • Codex's track-cache finding is fixed for the close path, a merge interaction between main's age-out tracking and dev's optional retention. The late-subscriber half predates this merge on dev, so it's left for a follow-up.
  • Interop (max-age) raced: the JS subscriber took the first announce event, which can be dev's live marker before the relay learns the route. It now waits for the age start, like the Rust arm.
  • The JS nbf check stays, matching Rust.
  • main has moved past e713c30 since this sync; the next sync picks that up.

Merging with a merge commit.

(Written by Claude Opus 5.5)

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.

3 participants