Repository navigation
feat(net)!: remove epochs from moq-transport - #7239
Conversation
Quest-Claim: a5c32d05d9bb8b26
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Drop the EPOCH fields from main's new request-stream code, and update main's dynamic-epoch restart test and identity guide for epochless moq-transport.
Main's joining-FETCH test and the moq-transport-18 e2ee transport case still expected an epoch over moq-transport, and the priority-update restart reads lite-07 alone as in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's moq-cli replacement and route-change suites asserted an in-place restart or a cross-route resume over moq-transport, which carried the epoch until this cut. Epochless moq-transport route loss stays covered by the pinned cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep draft 20 and announce takeover from main without their EPOCH parameter, and drop main's MoQ Epoch extension tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: f169a94.
Direction: removing the unused wire extension is a worthwhile simplification; retaining local/moq-lite epochs and changing moq-transport replacement tests to End+Start matches that boundary. No additional actionable bugs found in the inspected changes.
Known finding, not new: I agree with the solicit=false reordering issue already recorded in this PR's Review section. In rs/moq-net/src/ietf/subscriber.rs:2415–2431 and js/net/src/ietf/subscriber.ts:424–430, an overlapping replacement remains an update (or a no-op for equal routes), so a restart can retain the old consumer/cache. This now also affects our formerly epoch-capable peers. Carry the per-announcement-identity fix and a regression that delivers the new advertisement before the old reset into the follow-up; the ordered solicited path does not exercise it. Referencing the existing finding rather than duplicating an inline comment.
Verification: static inspection of Rust/JS negotiation, codecs, publisher/subscriber replacement and request paths, and changed restart/route/GOAWAY tests. I did not run tests or independently verify the reported CI/local test results.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — the full diff (66 files) removing the MoQ Epoch extension from moq-transport in Rust and JS, plus the doc/test/quest fallout.
- Wire and codecs. Deletes SETUP option
0x40B68and parameter0x40B69from the Rust (ietf/epoch.rs,epochentries inmod.rs/parameters.rs/peer.rs/session.rs) and JS (ietf/epoch.ts,setup_options.ts,parameters.ts,connection/handshake.ts,connection/extensions.ts) surfaces. All message codecs (subscribe,fetch,track,publish_namespace,subscribe_namespace) drop theirepochfield and parameter paths. - Publisher/subscriber logic. Removes in-place replacement (
Publisher::replaces,#replace,select's epoch forwarding), request epoch pinning, and the gained/lost-epoch violation. Replacement is now uniformly withdraw-then-advertise. I traced each removed branch (select,apply_update,updateAnnounce/#settleAnnounce,#updateAnnounce's newest-splice,aliases.ts) and confirmed the epoch was alwaysNoneon these paths once negotiation is gone, so the simplifications are behavior-preserving for moq-transport. - API/config.
setup::Extensions.epochand JSextensions.epochdeleted (JS api report regenerated);Ietf.Epochunexported. - Model epochs retained.
crate::Epoch,origin::Route::epoch,js/net/src/epoch.ts, and the local epoch pinning for the publisher's own track listing (Rustpublisher/tracks.rs, JS#listBroadcast→#resolve) are untouched, matching the stated boundary. - Tests/docs/quest. Epoch-over-moq-transport cases converted to epochless End+Start expectations; docs trimmed in nine files; the quest file deleted and back-links repointed.
Verification I ran: a repo-wide sweep for dangling references (extensions.epoch, epoch = false, Ietf.Epoch, moq-epoch, 0x40b68/9, ietf-epoch-cut) found none in code, config, or docs, and confirmed the one remaining /draft/moq-epoch mention is the intentional "unimplemented proposal" note in doc/concept/standard.md. I did not run CI.
The only behavioral consequence I found is the solicit=false reordering already recorded in the PR's Review section and re-flagged by the prior reviewer: a restart whose new PUBLISH_NAMESPACE overtakes the old reset is folded into the same route as an update. It is pre-existing for third-party peers, is now reachable by our own epochless peers, and is scoped to the per-announcement-identity follow-up (#7420). Nothing to change here.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
|
Landing summary for
(Written by Claude Opus 5.5) |
|
quest land removed this pull request from the queue: Conflicts with the base: quest/m1/announce-takeover.md, rs/moq-net/src/ietf/publisher.rs |
|
quest land removed this pull request from the queue: Conflicts with the base: js/net/src/ietf/subscriber.test.ts, rs/moq-net/src/ietf/publisher/tracks.rs |
…79e0eb2452b # Conflicts: # js/net/src/ietf/subscriber.test.ts # rs/moq-net/src/ietf/publisher/tracks.rs
|
Merged
(Written by Claude Opus 5.5) |
|
codex / Codex land fixer: ietf::Negotiated {
cluster: self.peer.negotiated(),
- epoch: self.epochs,
}
}
@@ -938,7 +931,6 @@ impl Publisher {
&self,
stream: &mut Stream<Transport, Version>,
path: &crate::Path,
- epoch: Option<crate::Epoch>,
) -> Result<Option<crate::broadcast::Consumer>, Error> {
let Some(origin) = self
.until_withdrawn(stream, |waiter| self.poll_serving_origin(waiter))
@@ -947,7 +939,7 @@ impl Publisher {
return Ok(None);
};
// The immediate lookup: answering a peer never starts discovery of its own.
- let requesting = origin.lookup(path.clone(), epoch.as_ref());
+ let requesting = origin.lookup(path.clone(), None);
self.until_withdrawn(stream, |waiter| requesting.poll_ok(waiter))
.await
.transpose()
@@ -985,42 +977,32 @@ impl Publisher {
///
/// The origin's announce cursor already filters routes through the peer
/// (control-plane split horizon); this only shapes what the wire can carry.
- /// `epochs` says the peer negotiated MoQ Epoch, so the route's instance travels too.
- fn select(&self, route: &crate::origin::Route, peer: &cluster::Peer, epochs: bool) -> Advert {
+ fn select(&self, route: &crate::origin::Route, peer: &cluster::Peer) -> Advert {
// A route that already passed through us is a reflection. The origin
// filters these on receive, so this is defensive.
if self.self_origin != crate::Hop::UNKNOWN && route.hops.contains(&self.self_origin) {
return Advert::None;
}
- // Forwarded unchanged, and never invented for a route that arrived without one.
- let epoch = route.epoch.clone().filter(|_| epochs);
if !peer.negotiated() {
- return Advert::Some(ietf::AdvertParams { cluster: None, epoch });
+ return Advert::Some(ietf::AdvertParams { cluster: None });
}
let cost = route.cost.value();
// Our own Hop ID is always the last entry, so the peer reconstructs the full
// path. A chain with no room left is a loop in all but name.
match cluster::Advert::forward(&route.hops, cost, self.self_origin) {
- Ok(advert) => Advert::Some(ietf::AdvertParams {
- cluster: Some(advert),
- epoch,
- }),
+ Ok(advert) => Advert::Some(ietf::AdvertParams { cluster: Some(advert) }),
Err(_) => Advert::None,
}
}
/// Handle an incoming bidi stream dispatched by the session.
- ///
- /// `epochs` says both sides negotiated MoQ Epoch: a request naming an instance on a
- /// session that did not breaks the session.
pub fn handle_stream(
&self,
id: u64,
body: ietf::Body,
stream: Stream<Transport, Version>,
codex
Both conflicts are resolved, and the whitespace check passes. Tests are blocked by missing local dependencies: Bun cannot resolve `@moq/clock`, and Cargo lacks the cached `uniffi` Git dependency. I’ll commit the merge resolution and write the result file.
exec
/bin/bash -lc "git -c core.hooksPath=/dev/null commit -m \"Merge base and preserve epoch removal across test and publisher deletions\"
python3 - <<'PY'
import json, subprocess
from pathlib import Path
head=subprocess.check_output(['git','rev-parse','pr-7239'],text=True).strip()
subprocess.run(['git','merge-base','--is-ancestor','846eb146c',head],check=True)
subprocess.run(['git','merge-base','--is-ancestor','base',head],check=True)
assert subprocess.check_output(['git','rev-parse','batch'],text=True).strip().startswith('846eb146c')
Path('quest-land-result.json').write_text(json.dumps([{'number':7239,'action':'fixed','head':head,'reason':'Merged base; retained epoch-test removal and base deletion of the Rust track publisher.'}],indent=2)+'\\n')
PY
git status --short; git log -1 --format='%H %P'; git diff HEAD --check" in /work
succeeded in 0ms:
[pr-7239 254250c58] Merge base and preserve epoch removal across test and publisher deletions
?? quest-land-result.json
254250c58de3245351ac470e224af8aab6f48f3f 846eb146cf1a3927e03327c06630eaecf14c2cf0 44e85d8efb8e47aaefedc49dfd2519fa995fda6b
codex
Fixed PR #7239 by merging base and resolving both conflicts mechanically.
Head: `254250c58de3245351ac470e224af8aab6f48f3f`
[quest-land-result.json](/work/quest-land-result.json) is uncommitted. Whitespace checks passed; tests were blocked by missing local dependencies.
tokens used
47,263
Fixed PR #7239 by merging base and resolving both conflicts mechanically.
Head: `254250c58de3245351ac470e224af8aab6f48f3f`
[quest-land-result.json](/work/quest-land-result.json) is uncommitted. Whitespace checks passed; tests were blocked by missing local dependencies.
fixer result written
(written by codex / Codex) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — the delta since the prior pullfrog review at 846eb146 (the 3cf8b7106 merge of main at 44e85d8).
- Merged
mainand re-applied the epoch removal. Net effect of the merge for every touched file is exactlymainplus the MoQ Epoch removal. A sweep ofrs/moq-net/src/ietf/andjs/net/src/ietf/finds noepoch/Epoch/0x40B68/0x40B69left except the unrelated authepoch: u64permit and modelcrate::Epochin tests; theepoch: Nonefields remaining infuzz.rs,test_interop.rs, andpath/mod.rsarelite::(moq-lite) types that intentionally keep epochs. - Reconciled the IETF epoch tests with
main's controlled clock.js/net/src/ietf/subscriber.test.tskeepsmain'sElapsed/sleep/timeout/yieldNowimports (nextStreamnow usestimeout) while the branch's deletion of the six MoQ Epoch extension tests and theirinlineEpoch/publishEpochhelpers survives; every imported helper is still used. - Kept
main's deletion of the track-listing publisher.rs/moq-net/src/ietf/publisher/tracks.rsstays deleted (removed by #7236), so the branch's epoch-only edits there are gone rather than reintroduced. - No dangling links. A repo-wide sweep finds no reference to the deleted
quest/m1/ietf-epoch-cut.md, nor toextensions.epoch,epoch = false,Ietf.Epoch, or0x40b68/9; the/draft/moq-epochmention indoc/concept/standard.mdis the intentional "unimplemented proposal" note.
The known solicit=false restart-ordering risk remains deferred to the per-announcement-identity follow-up (#7420), unchanged by this merge.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
|
quest land removed this pull request from the queue: Conflicts with the base: js/e2ee/src/transport.test.ts, rs/moq-net/src/ietf/peer.rs, rs/moq-net/src/ietf/publisher.rs, rs/moq-net/src/ietf/session.rs, rs/moq-net/src/ietf/subscriber.rs, rs/moq-net/tests/integration/extensions.rs, rs/moq-net/tests/integration/multi_cdn.rs, rs/moq-net/tests/integration/replacement.rs, rs/moq-net/tests/integration/route_change.rs |
|
codex / Codex land fixer: futures = { workspace = true, optional = true }
hashbrown = { workspace = true }
hashlink = { workspace = true }
kio = { workspace = true, features = ["macros"] }
moq-pattern = { workspace = true, features = ["serde"] }
num_enum = { workspace = true }
rand = { workspace = true }
rangemap = { workspace = true }
serde = { workspace = true }
slab = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }
uuid = { workspace = true }
[dev-dependencies]
criterion = { package = "bench-harness", path = "../bench-harness" }
futures = { workspace = true }
# The tests' executor, with simulated time.
kio = { path = "../kio", features = ["runtime", "sim"] }
proptest = { workspace = true }
serde_json = { workspace = true }
# The benches run on tokio. test-util (tokio::time::pause/advance) is test-only, so
# it must not leak into the normal dependency feature set.
tokio = { workspace = true, features = ["rt", "test-util", "time"] }
tracing-test = { workspace = true }
# Optional per-thread CPU timing in the session benchmark.
[target.'cfg(unix)'.dev-dependencies]
libc = { workspace = true }
# Writes the generated fuzzer corpus to disk. Needs the `fuzz` feature, so a default
# `--all-targets` build skips it rather than failing to find the module.
[[example]]
name = "fuzz-seeds"
path = "examples/fuzz-seeds.rs"
required-features = ["fuzz"]
# Lands peer claims through the hidden `fuzz` module, as a session does.
[[bench]]
name = "origin"
harness = false
required-features = ["fuzz"]
# Reaches the crate-private session view of an origin through the hidden `fuzz` module.
[[bench]]
name = "viewers"
harness = false
required-features = ["fuzz"]
# Reaches the private announce codec through the hidden `fuzz` module.
[[bench]]
name = "announce"
harness = false
required-features = ["fuzz"]
# Reaches the crate-private session snapshot through the hidden `fuzz` module.
[[bench]]
name = "synced"
harness = false
codex
The conflicts include a behavioral decision: base adds tests requiring EPOCH requests to enforce instance pinning and reject use without negotiation, while #7239 removes that extension and treats EPOCH as unknown. Resolving this would require choosing protocol behavior, so I’ll hand back the PR and leave its branch unchanged.
exec
/bin/bash -lc 'git merge --abort; git rev-parse pr-7239; git status --short; git log base --oneline -8' in /work
succeeded in 4333ms:
Updating files: 34% (272/780)
Updating files: 35% (273/780)
Updating files: 36% (281/780)
Updating files: 37% (289/780)
Updating files: 38% (297/780)
Updating files: 39% (305/780)
Updating files: 40% (312/780)
Updating files: 41% (320/780)
Updating files: 42% (328/780)
Updating files: 43% (336/780)
Updating files: 44% (344/780)
Updating files: 45% (351/780)
Updating files: 46% (359/780)
Updating files: 47% (367/780)
Updating files: 48% (375/780)
Updating files: 49% (383/780)
Updating files: 50% (390/780)
Updating files: 51% (398/780)
Updating files: 52% (406/780)
Updating files: 53% (414/780)
Updating files: 54% (422/780)
Updating files: 55% (429/780)
Updating files: 56% (437/780)
Updating files: 56% (440/780)
Updating files: 57% (445/780)
Updating files: 58% (453/780)
Updating files: 59% (461/780)
Updating files: 60% (468/780)
Updating files: 61% (476/780)
Updating files: 62% (484/780)
Updating files: 63% (492/780)
Updating files: 64% (500/780)
Updating files: 65% (507/780)
Updating files: 66% (515/780)
Updating files: 67% (523/780)
Updating files: 68% (531/780)
Updating files: 69% (539/780)
Updating files: 70% (546/780)
Updating files: 71% (554/780)
Updating files: 72% (562/780)
Updating files: 73% (570/780)
Updating files: 74% (578/780)
Updating files: 75% (585/780)
Updating files: 76% (593/780)
Updating files: 77% (601/780)
Updating files: 78% (609/780)
Updating files: 79% (617/780)
Updating files: 80% (624/780)
Updating files: 81% (632/780)
Updating files: 82% (640/780)
Updating files: 83% (648/780)
Updating files: 84% (656/780)
Updating files: 85% (663/780)
Updating files: 86% (671/780)
Updating files: 87% (679/780)
Updating files: 87% (682/780)
Updating files: 88% (687/780)
Updating files: 89% (695/780)
Updating files: 90% (702/780)
Updating files: 91% (710/780)
Updating files: 92% (718/780)
Updating files: 93% (726/780)
Updating files: 94% (734/780)
Updating files: 95% (741/780)
Updating files: 96% (749/780)
Updating files: 97% (757/780)
Updating files: 98% (765/780)
Updating files: 99% (773/780)
Updating files: 100% (780/780)
Updating files: 100% (780/780), done.
3cf8b710651f31cadc2d3c1a1190b4a6a07e8ac2
f194edc23 fix(bench): isolate comparison worktrees from Cargo configuration (#7445)
664b1aad2 perf(net): skip refusal for group ranges; attribute the paired bench regressions (#7253)
32391c452 perf(net): park memory-transport reads and writes on the close only when they wait (#7262)
8ff7c311d Probing beside Cubic meets the deadline budget (#7429)
090fec2e4 feat(relay): one TCP port for HTTP, RTMP, RTMPS, and tls:// (#7362)
caef9b3fc quest: plan the land gate's CI follow-ups (#7456)
08e71cd3d fix(net): keep DYNAMIC_GROUPS through an opted-out draft-22 resume (#7383)
68fb455ba fix(net): take a reserved group without asking its cursor again (#7032)
exec
/bin/bash -lc "python3 - <<'PY'
import json
result = [{\"number\":7239,\"action\":\"handback\",\"diagnosis\":\"Base conflicts with epoch removal in nine files; new publisher tests require EPOCH instance pinning and rejection without negotiation, whereas this PR removes EPOCH and treats it as unknown, requiring a protocol behavior decision.\",\"recommendation\":\"Have the author reconcile base's new epoch-specific request and replacement handling with extension removal, update the affected tests, and rerun Rust and JavaScript checks.\"}]
with open('quest-land-result.json','w') as f:
json.dump(result,f,indent=2)
f.write('\\n')
PY
git status --short" in /work
succeeded in 0ms:
?? quest-land-result.json
codex
PR #7239 handed back: base’s new EPOCH enforcement conflicts with the PR’s extension removal and requires a protocol behavior decision.
Branch unchanged. Diagnosis and recommendation written to [quest-land-result.json](/work/quest-land-result.json), left uncommitted.
tokens used
48,378
PR #7239 handed back: base’s new EPOCH enforcement conflicts with the PR’s extension removal and requires a protocol behavior decision.
Branch unchanged. Diagnosis and recommendation written to [quest-land-result.json](/work/quest-land-result.json), left uncommitted.
fixer result written
(written by codex / Codex) |
Drop the moq-transport epoch code main added since the last merge: the EPOCH Setup Option in the new SETUP parser, the epoch in the kio Resolve machine and the alongside-TRACK_STATUS FETCH, and the previous-epoch request retention (and its test) from the credit-free advertisement loop. Main's ported MoQ Epoch tests stay deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…poch The JS moq-transport publisher's #resolve kept an epoch parameter no caller passes since requests no longer carry EPOCH. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged
(Written by Claude Opus 5.5) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — the delta since the prior pullfrog review at 3cf8b71: the b21ab7422 merge of main at 50c4efdbc0 and the 6fed268 fix.
- Merged
mainand re-applied the epoch removal. The reconciliation drops main's newer MoQ Epoch additions: the EPOCH SETUP option, the request epoch in the kioResolvemachine and in the FETCH alongside TRACK_STATUS, and the previous-epoch request retention in the advertisement loop.NamespaceRequesthas nopreviousfield andResolve::new/origin.lookuptake no epoch. - Dropped the unused
epochparameter from the JS publisher's#resolve. All three call sites pass onlyname/signal, solocal(name)anddemand(name, undefined, signal)are behavior-preserving. - Reconciled the epoch tests.
replacement.rsrenamesepoch_ietftoepoch_is_stripped_ietfand extendsepochless_ietfto draft 18;route_change.rsmovesietf_18/ietf_22intopinned_testsand drops the epoch-only flap/lagging-route cases;extensions.rsdeletesan_epoch_crosses_only_when_both_offer_it;restart.rs/epochs.rsexpect End+Start for every non-lite-07 wire. - Kept the e2ee assertion. The transport matrix takes
main's lite-05timed=truechange while keepingrouted=falsefor moq-transport-18, so it still asserts no route epoch over moq-transport.
Verification I ran: cargo check -p moq-net --tests passes on 6fed268, and repo-wide sweeps for 0x40b68/9, Ietf.Epoch, extensions.epoch, and epoch = false return nothing. The known solicit=false restart-ordering risk remains deferred to the per-announcement-identity follow-up (#7420), unchanged by this merge.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
Main's #7239 removes MoQ Epoch from moq-transport. The conflicts in fetch.rs, publisher.rs and subscriber.rs keep this PR's request tokens and namespace verification state and drop the epoch parameters, the restart replacement check and the epoch tests with main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-dev#7239 merged, so route_dies_without_an_epoch's pinned tests already run moq-transport 18 and 22 epochless through the shared topology. The Plan's "whichever lands first" and "lite-04 to 06 alone" lines were stale. Only lite-07-wip needs the epochless topology. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Problem
moq-transport's unused MoQ Epoch extension adds negotiation, request pinning, and advertisement replacement machinery. No third party implements it. The quest (decided with the maintainer 2026-10-28) removes it and keeps moq-lite 07 epochs.
Approach
Ietf.Epoch, and regenerate the JS public API report.doc/concept/identity.mdand the takeover paragraph indoc/concept/moq-lite.mdfrommain.mainbrought in draft 20 (moq-dev/moq#7190), announce takeover (moq-dev/moq#6994), and new tests that assumed epochs over moq-transport. The merges resolve them as follows:an_epoch_crosses_only_when_both_offer_it, the pinned-request publisher tests, and the draft-20epoch.test.tschange);moq-net-testsrestart.rs(dynamic_epoch,priority_update) andmoq-cliepochs.rs;flaps_ietf_22andietf_*_resumes_after_a_lagging_route_dies, which assert a cross-route resume that needs the epoch. Epochless moq-transport route loss stays covered byroute_change::pinned_tests(ietf_18,ietf_22).mainat50c4efdbc0removed the moq-transport epoch code main added since the last merge:Resolvemachine (moq-dev/moq#7284) and in the FETCH sent alongside TRACK_STATUS (moq-dev/moq#7332);a_stalled_epoch_replacement_is_bounded_and_withdrawntest. The loop's generic one-opening-advertisement gate and early-OK hold stay;kioports of the already-deleted MoQ Epoch tests stay deleted, and this branch's restart tests moved frommoq_clocktokio::clock(moq-dev/moq#7027).#resolvedrops its unusedepochparameter.quest/m1/ietf-epoch-cut.mdand its links. The prose reference inquest/m1/announce-takeover.mdnow points at this PR.Impact
setup::Extensions::epochand JSextensions.epoch. Delete everyepochextension setting, includingepoch = falseandextensions.epoch = false, from application and relay configuration. Rust rejects the old setting at startup (deny_unknown_fields). Remove anyIetf.Epochimports.0x40B68and never sends or interprets parameter0x40B69. Every moq-transport hop is epochless, so replacement sessions and publisher-instance changes need readers to follow the announcement and request the path again. Use moq-lite 07 on every hop for epoch continuity.MIGRATE.mdfrom this section.Validation
All suites ran locally through
quest gate.just ci origin/mainpassed on6fed26889f, after merging main at50c4efdbc0(Rust and JS check/test, markdown, quest, shell, gh). It passed earlier on the merge head3cf8b71065.just ci origin/main: every module passed on2be80f17c4, including Rust check, test, and feature shapes, JS check and test, markdown, quest, and shell. It passed again on the final headf169a9457a.just test interop --all: 182 passed, 0 failed.just test interop --all --versions moq-transport-18,moq-transport-20,moq-transport-22: 214 passed, including everygoawayandreverse-goawaycase on all three drafts.js -> jscase failed on drafts 20 and 22, timing out on "resumed playback" after the relay answered the re-subscribe withPUBLISH_DONE … internal error.just test wire-compat: the token, session, catalog, and container lanes passed. 72 session cells ran; the 49 skips are the planned lite-07 breaks. The compat matrix covers only moq-lite.Two earlier interop/wire-compat attempts failed only because mbx pruned the shared
target/mid-run. Wire-compat passed with a worktree-localCARGO_TARGET_DIR.Review
quest review, gpt-6.1-sol, medium effort) on6fed26889fe8680ec78f51617cc6e9193c5ed665: 0 findings (round 2 of a new session; round 1 on the merge commitb21ab7422falso reported 0). The merge withmainat50c4efdbc0resolved nine files by hand:rs/moq-net/src/ietf/{peer,publisher,session,subscriber}.rs,js/e2ee/src/transport.test.ts, and theextensions,multi_cdn,replacement, androute_changeintegration tests.3cf8b710651f31cadc2d3c1a1190b4a6a07e8ac2, after mergingmainwith moq-dev/moq#7236 and moq-dev/moq#7329.--deep, gpt-6-astra) reported 0 findings on60c8cd3425and46249bbadb. A Claude Opus 5.5 reviewer on2be80f17c4raised three findings: the e2ee test fix (fixed), the dropped flap/lagging-route tests (refuted: covered epochless byroute_change::pinned_tests), and thesolicit = falserestart reordering (accepted and deferred to per-announcement identity,quest/m1/api-audit/route/identity.md).Choices made without asking
main's newer plan text when the quest file conflicted, then deleted the quest as the brief asked.mainadded after this branch was cut, since the behavior they assert no longer exists.a_stalled_epoch_replacement_is_bounded_and_withdrawnwith the previous-epoch retention it tested, rather than rewriting it epochless: an epochless restart withdraws before it re-advertises, andstalled_advertisements_observe_local_and_peer_endsstill covers withdrawal under stalled credit.Follow-ups
js -> jsmoq-transport 20/22 resume failure (PUBLISH_DONEinternal error on re-subscribe) is pre-existing onmain, and no quest owns it yet. It belongs under Interop and Video pass on main.quest-plan/route-origin-api) plans the epoch's split into identity and epoch and builds on this cut: moq-transport carries no identity, and a receiving session mints one. It still links/quest/m1/ietf-epoch-cut.mdin several places, which this PR deletes. Whichever lands second must replace those links, for example with this PR's URL, orquest checkfails.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code