Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5a2994a
quest(audio-quality-harness): open questline
kixelated Sep 28, 2026
efb32eb
Merge remote-tracking branch 'origin/main' into aqh-readme
kixelated Sep 29, 2026
29b0a64
test(audio-quality): grade browser audio playout against a budget, ni…
kixelated Sep 29, 2026
165377f
chore: claim shaper profiles quest
kixelated Sep 29, 2026
1c47bf8
feat(shaper): pipe TCP on the shaper's port to the target, as an option
fperex Sep 25, 2026
a909d5f
feat(shaper): a gaussian jitter model that keeps the order, as an option
fperex Sep 25, 2026
6b7964c
feat(shaper): one link each way for every client, as an option
fperex Sep 25, 2026
7e7b729
feat(shaper): batches that release datagrams together, as an option
fperex Sep 25, 2026
b6230c5
feat(shaper): steps that change a profile part-way through a run
fperex Sep 25, 2026
f56f477
feat(shaper): named profiles for both directions, loaded from TOML
fperex Sep 25, 2026
c630613
feat(shaper): a JSON report of the counters, as an option
fperex Sep 25, 2026
f564161
fix(shaper): send a datagram that is already due at once, not on a timer
fperex Sep 25, 2026
7804662
docs(shaper): a README for the shaper's usage and its options
fperex Sep 25, 2026
53137d6
test(audio-quality): grade bursty and changing paths
kixelated Sep 29, 2026
756200e
fix(shaper): verify fails a step no traffic reached, and a late datag…
kixelated Sep 29, 2026
2130e8a
Merge remote-tracking branch 'origin/main' into quest/m0/audio-qualit…
kixelated Sep 29, 2026
d9a9de7
fix(shaper): refuse a step that changes nothing and a batch of one
kixelated Sep 29, 2026
748447b
fix(audio-quality): measure a step row from before its step, and coun…
kixelated Sep 29, 2026
2ecb0ab
fix(shaper): refuse jitter with no delay to vary
kixelated Sep 29, 2026
cc791f0
Merge remote-tracking branch 'origin/main' into questline-sync
kixelated Sep 29, 2026
c1723fc
Merge remote-tracking branch 'origin/quest/m0/audio-quality-harness/R…
kixelated Sep 29, 2026
0f024e3
test(audio-quality): record real arrival traces and grade their repla…
kixelated Sep 29, 2026
04070bc
Merge origin/quest/m0/audio-quality-harness/README into quest/m0/audi…
kixelated Sep 29, 2026
94c3483
test(audio-quality): count browser rows apart from replays; size the …
kixelated Sep 29, 2026
86b3686
Merge remote-tracking branch 'origin/main' into quest/m0/audio-qualit…
kixelated Sep 30, 2026
b7a48e6
fix(moq-shaper): verify every step's phase saw traffic
kixelated Oct 1, 2026
7ae87b1
Merge remote-tracking branch 'origin/quest/m0/audio-quality-harness/R…
kixelated Oct 1, 2026
01ab236
style(moq-shaper): format
kixelated Oct 1, 2026
beeb93d
fix(moq-shaper): require traffic before the first step too
kixelated Oct 1, 2026
be6978c
Merge pull request #4478 from moq-dev/quest/m0/audio-quality-harness/…
kixelated Oct 1, 2026
0b53477
Merge origin/main into quest/m0/audio-quality-harness/README
kixelated Oct 1, 2026
9fbc43e
fix(test): pass audio-quality recipe args through after the merge
kixelated Oct 1, 2026
cd71f20
Merge origin/main into quest/m0/audio-quality-harness/README
kixelated Oct 1, 2026
fea8fe4
quest: finish the audio quality harness line
kixelated Oct 1, 2026
a5ecd60
fix(moq-shaper): charge each step phase only its own traffic; drop ra…
kixelated Oct 1, 2026
2278508
fix(audio-quality): count a gap the run ends in; replay to the record…
kixelated Oct 1, 2026
7c230c6
fix(audio-quality): resolve the tap's finish only on its own answer
kixelated Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/audio-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Audio quality

# Grades the recorded-trace replays of test/audio-quality against their exact
# budgets on every PR that can move them. They replay the player's container
# consumer and rings on a simulated clock, so they are deterministic and take
# seconds, unlike the browser rows, which stay in nightly.yml.
on:
pull_request:
paths:
- "js/watch/**"
# The container consumer decides what a replay delivers, waits for, and skips, on the
# groups, tracks, and signals underneath it.
- "js/hang/**"
- "js/net/**"
- "js/signals/**"
- "test/audio-quality/**"
- "test/lib/**"
- "test/justfile"
- ".github/workflows/audio-quality.yml"

concurrency:
group: audio-quality-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
replay:
name: Replay
runs-on: ubuntu-24.04-arm
timeout-minutes: 20

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: DeterminateSystems/nix-installer-action@1d87d45818068401a10cf16bdc5f00b24994a83f # main
with:
determinate: false
# Trust the flake's cachix substituter; see check.yml.
extra-conf: |
extra-substituters = https://kixelated.cachix.org
extra-trusted-public-keys = kixelated.cachix.org-1:CmFcV0lyM6KuVM2m9mih0q4SrAa0XyCsiM7GHrz3KKk=

- name: Replay
run: nix develop --command just test audio-quality --replays --enforce
shell: bash -leo pipefail {0}
env:
# Somewhere upload-artifact can reach; the harness default is under $TMPDIR.
MOQ_TEST_RUNS: ${{ runner.temp }}/moq-test-runs

# The harness keeps a failing run's directory: every row's samples and summary.
- name: Keep the failing run
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: audio-quality-replay
path: ${{ runner.temp }}/moq-test-runs/
retention-days: 7
if-no-files-found: ignore
57 changes: 57 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ name: Nightly
# the wheel builds in a manylinux container, the Kotlin/Swift/Go/Dart packages
# link the FFI on every platform) and nothing notices until the tag is pushed.
#
# `audio-quality` is here because of what it measures. It plays twenty-four rows of
# audio in real time, a minute each, which no merge gate should carry, and every
# number it grades is a timing one that moves with whatever else the runner is
# doing. A per-PR arm would fail on unrelated load often enough to be ignored;
# nightly it competes with nothing, and a regression surfaces a day late against
# a budget that still means something. The recorded-trace replays are the
# exception: deterministic and seconds long, so audio-quality.yml also gates
# PRs on them.
#
# A failure here lands on main rather than being caught in review, which is the
# accepted trade. Anything that must block a merge belongs in check.yml.

Expand Down Expand Up @@ -200,6 +209,54 @@ jobs:
NEXTEST_PROFILE: ci
MOQ_STRICT: 1

# Plays the matrix in headless Chromium through moq-shaper and grades what the
# listener heard against test/audio-quality/budgets.json. ARM64 like wasm.yml,
# the only architecture cache.yml warms a Rust store for.
audio-quality:
name: Audio quality
runs-on: ubuntu-24.04-arm
# Twenty-four rows at a minute each, plus the relay, CLI, and shaper built from source.
timeout-minutes: 60
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@ceedf095f4ec1a097402bc6bd80831f2e1a6fde6 # main
with:
tool-cache: false
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: DeterminateSystems/nix-installer-action@1d87d45818068401a10cf16bdc5f00b24994a83f # main
with:
determinate: false
extra-conf: |
extra-substituters = https://kixelated.cachix.org
extra-trusted-public-keys = kixelated.cachix.org-1:CmFcV0lyM6KuVM2m9mih0q4SrAa0XyCsiM7GHrz3KKk=
- name: Rust cache
uses: ./.github/actions/rust-cache
# Playwright's Chromium isn't in the nix devShell; `--with-deps` installs
# its apt runtime libs, and run.sh's own install then no-ops.
- name: Playwright Chromium
run: nix develop --command bash -c "bun install --frozen-lockfile && bunx playwright install --with-deps chromium"
shell: bash -leo pipefail {0}
- name: Audio quality
run: nix develop --command just test audio-quality --enforce
shell: bash -leo pipefail {0}
env:
# Somewhere upload-artifact can reach; the harness default is under $TMPDIR.
MOQ_TEST_RUNS: ${{ runner.temp }}/moq-test-runs
# The run directory is the diagnosis: each process's log, the shaper's
# counters, the raw samples, and every row's summary. The harness keeps it
# on a failure without being asked.
- name: Keep the failing run
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: audio-quality-run
path: ${{ runner.temp }}/moq-test-runs/
retention-days: 7
if-no-files-found: ignore

# Every tag-driven release workflow, run against main with publishing skipped:
# the workflows gate their publish jobs on `github.ref_type == 'tag'`, and no
# secrets are passed, so a dry-run cannot publish even by accident.
Expand Down
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ hex = "0.4"
# HMAC-SHA256 for the mDNS membership proofs (moq-tokio's `mdns` feature).
hmac = "0.13"
humantime = "2.3"
humantime-serde = "1.1.1"
hyper-util = { version = "0.1.21", features = ["tokio"] }
io-uring = "0.7.14"
jsonwebtoken = "11"
Expand Down
72 changes: 72 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading