Skip to content

docs(quest): plan follow-ups from the next-16 quest wave - #4140

Open
kixelated wants to merge 2 commits into
mainfrom
claude/plan-follow-ups
Open

kixelated wants to merge 2 commits into
mainfrom
claude/plan-follow-ups

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

The agents from the latest quest wave (#4108-#4126) reported follow-ups that no quest covered.

Approach

Planned with the maintainer:

m1

  • archive/paced-replay [M]: moq import archive pushes recorded groups to live subscribers on one shared clock per import, like ffmpeg -re, so export ts and web watch play a replay.
  • archive/provenance [S]: a replay's catalog archive entry names its timeline, replay path, store URL (no credentials), and format version.
  • broadcast-close/kotlin-end [XS]: Kotlin exposes close() as end(), since AutoCloseable.close() takes the name. remove.md now requires it, so Kotlin keeps a forced end.
  • import-discontinuity [S]: import::Track::discontinuity(), called by moqsink on a seek and exposed in libmoq and moq-ffi. This replaces the "add one when such a caller appears" note in jitter-flush-clock.md.
  • js-bare-fin [S]: @moq/net aborts on a bare FIN, matching Rust (fix(net): end an IETF subscription from its PUBLISH_DONE #4083) and the drafts. Requires JS track tail.
  • test-flakes [M]: fix three tests that fail under just check load (two JS timeouts, and noq_cert_reload running out of file descriptors) at the cause, without raising timeouts.

m2

  • archive-recovery-listing [M], archive-backward-timestamps [XS]: DVR recovery listing proportional to change, and refusing backward timestamps on resume.
  • auth-expired-error [S]: an additive Error::Expired across lite, moq-transport, JS, and the bindings.
  • obs-wave-layout [XS]: the OBS source maps channel counts to WAVE default layouts.
  • aac-encode-refusal updated: JS already refuses (feat(audio): carry surround layouts through decode, remix, and playback #4119), so Rust refuses to match; a PCE is a later additive change.

Impact

None: quest files only.

Alternatives

  • Per-subscriber replay clocks (VOD-like), rejected because viewers wouldn't be in sync.
  • Ending the broadcast when the FFI handle is released, in every binding, rejected in favor of a Kotlin-only rename.
  • Relaxing Rust to accept a bare FIN, rejected because it contradicts the drafts.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review September 25, 2026 12:47
@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 36 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: f93b131b-328b-48c0-abae-8eac79c26e1d

📥 Commits

Reviewing files that changed from the base of the PR and between fd31194 and e247818.

📒 Files selected for processing (17)
  • quest/m1/README.md
  • quest/m1/archive/README.md
  • quest/m1/archive/paced-replay.md
  • quest/m1/archive/provenance.md
  • quest/m1/broadcast-close/README.md
  • quest/m1/broadcast-close/kotlin-end.md
  • quest/m1/broadcast-close/remove.md
  • quest/m1/import-discontinuity.md
  • quest/m1/jitter-flush-clock.md
  • quest/m1/js-bare-fin.md
  • quest/m1/test-flakes.md
  • quest/m2/README.md
  • quest/m2/aac-encode-refusal.md
  • quest/m2/archive-backward-timestamps.md
  • quest/m2/archive-recovery-listing.md
  • quest/m2/auth-expired-error.md
  • quest/m2/obs-wave-layout.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 25, 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-25T12:57:57.471068Z 3610b84 Draft marked ready
ℹ️ 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.

@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: 3610b8463e

ℹ️ 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 on lines +7 to +9
in `moq_mux::codec::aac::Config::encode`, as `@moq/hang`'s
`audioSpecificConfig` already refuses since #4119. This mirrors the parse
side, which since #4093 refuses reserved values instead of guessing stereo.

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 Keep the JavaScript AAC refusal in scope

@moq/hang does not already refuse unsupported channel counts: js/hang/src/util/aac.ts:47-53 returns stereo configuration 2 for every unsupported count, and its test explicitly verifies that 7 channels encode as stereo. Limiting this quest to Rust therefore leaves the silent channel-layout corruption in JavaScript. Restore the JS fallibility change and its tests instead of treating #4119 as having landed it.

AGENTS.md reference: AGENTS.md:L16-L17

Useful? React with 👍 / 👎.

Comment on lines +18 to +20
- A timeline gap is skipped at pace (the clock keeps running). A growing
archive is followed as new timeline segments land. A finite archive ends
each track after its last group.

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 Define how paced replay learns finality

The archive contract explicitly has no completion marker (quest/m1/archive/README.md:60-75), and the reader deliberately treats a missing tail as potentially growing, crashed, or incomplete (quest/m1/archive/reader.md:45-49). Consequently, after the last currently visible segment, the importer cannot distinguish a finite archive that should end its tracks from a growing archive it should continue following. Require an explicit out-of-band finality or one-shot replay mode before promising both behaviors.

Useful? React with 👍 / 👎.

Comment on lines +11 to +12
- Rename the method for Kotlin only in `rs/moq-ffi/uniffi.toml`; every other
binding keeps `close()`. Kotlin's `close()` still only releases the handle.

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 Wire the Kotlin rename into binding generation

rs/moq-ffi/uniffi.toml does not exist, and neither Kotlin generation path loads such a file: kt/scripts/generate.sh:80-82 and rs/moq-ffi/build.sh:166-170 invoke bindgen without --config (only the Dart invocation supplies one). Implementing this bullet as written therefore cannot produce end(), while remove.md now depends on this quest before deleting Kotlin's only force-end method. Specify a generated API or wrapper approach that both generation paths actually consume.

AGENTS.md reference: AGENTS.md:L64-L67

Useful? React with 👍 / 👎.

@kixelated

Copy link
Copy Markdown
Collaborator Author

MERGE

Positive improvement? Yes. Pure quest planning from the next-16 wave (#4108–#4126): concrete m1 items (archive/paced-replay, archive/provenance, broadcast-close/kotlin-end, import-discontinuity, js-bare-fin, test-flakes) and m2 items (archive-recovery-listing, archive-backward-timestamps, auth-expired-error, obs-wave-layout, plus an updated aac-encode-refusal now that JS already refuses in #4119). No code, API, or wire change. The write-ups name goals, plans, required parents, and rejected alternatives (per-subscriber replay clocks, ending the broadcast on every FFI drop, relaxing Rust bare-FIN), which is what this line needs before the next wave.

Worth the complexity? Yes—cheap bookkeeping. XS/S/M sizing and README wiring keep the queue legible. Notable calls look right: shared clock for paced replay (viewers stay in sync), Kotlin-only end() rename forced by AutoCloseable, JS bare FIN matching Rust/#4083 and the drafts, Error::Expired as an additive #[non_exhaustive] variant, and AAC Rust refusal to match JS with PCE deferred as a later additive change. test-flakes correctly insists on fixing causes (input size / FD leak / nextest concurrency) rather than raising timeouts.

Different approach? Not for a docs-only plan PR. Execution choices (e.g. checkpointed listing marker vs list_with_offset for DVR recovery) belong on the implementing PRs. One process note: keep test-flakes and the archive recovery quests from growing scope creep—each already has a crisp acceptance shape.

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

This branch has not been deployed

No deployments
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.

1 participant