Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
72 changes: 53 additions & 19 deletions .github/workflows/github-shapes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ on:
paths:
- .github/workflows/github-shapes.yml
- docs/design/github-shapes-200.md
- docs/design/github-shapes-200-pns-free.md
- tools/compat-corpus/github_shapes*.py
- tools/compat-corpus/decoded_output.py
- tools/compat-corpus/encode_breadth.py
- tools/compat-corpus/tests/test_github_shapes.py
- tools/compat-corpus/tests/test_github_shapes*.py
- scripts/install-oracle-ffmpeg.sh
- scripts/install-x264.sh
- scripts/oracle*
Expand All @@ -27,6 +28,11 @@ on:
description: Full merged main SHA containing the registration and tools
required: true
type: string
registration:
description: Acquire both registered recipes at the same candidate
type: choice
options: [paired]
default: paired

permissions:
contents: read
Expand Down Expand Up @@ -57,6 +63,7 @@ jobs:
timeout-minutes: 240
env:
COMMIT: ${{ inputs.commit }}
REGISTRATION: ${{ inputs.registration }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
Expand All @@ -66,14 +73,29 @@ jobs:
run: |
set -euo pipefail
[ "$GITHUB_REF" = refs/heads/main ] || { echo '::error::main_dispatch_required'; exit 1; }
[ "$REGISTRATION" = paired ] || { echo '::error::fixture_registration'; exit 1; }
[[ "$COMMIT" =~ ^[0-9a-f]{40}$ ]] || { echo '::error::candidate_sha'; exit 1; }
git merge-base --is-ancestor "$COMMIT" origin/main || { echo '::error::candidate_not_merged'; exit 1; }
mkdir -p "$RUNNER_TEMP/oracle-owner/scripts"
cp scripts/test_oracle.py scripts/oracle_pin.py scripts/oracle_pin_macos.py scripts/oracle-ffmpeg.env \
scripts/oracle-ffmpeg-macos.env "$RUNNER_TEMP/oracle-owner/scripts/"
git checkout --detach "$COMMIT"
test -f docs/design/github-shapes-200.md
test -f docs/design/github-shapes-200-pns-free.md
test -f tools/compat-corpus/github_shapes.py
- name: Require private evidence retention
env:
R2_ENDPOINT: ${{ secrets.COREAV_CORPUS_R2_ENDPOINT }}
R2_ACCESS_KEY_ID: ${{ secrets.COREAV_CORPUS_R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.COREAV_CORPUS_R2_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ vars.COREAV_CORPUS_R2_BUCKET }}
run: |
python3 - <<'PY'
import os
names = ('R2_ENDPOINT', 'R2_ACCESS_KEY_ID', 'R2_SECRET_ACCESS_KEY', 'R2_BUCKET')
if not all(os.environ.get(name) for name in names):
raise SystemExit('private_retention_configuration')
PY
- name: Install build dependencies and pinned programs
run: |
set -euo pipefail
Expand All @@ -83,6 +105,7 @@ jobs:
scripts/install-x264.sh "$RUNNER_TEMP/oracle"
python3 -m venv "$RUNNER_TEMP/aac-python"
"$RUNNER_TEMP/aac-python/bin/pip" install --quiet --only-binary=:all: --require-hashes -r scripts/aac-pns-requirements.txt
"$RUNNER_TEMP/aac-python/bin/pip" install --quiet 'boto3==1.35.36'
echo "$RUNNER_TEMP/aac-python/bin" >> "$GITHUB_PATH"
- name: Build the full feature set
run: |
Expand All @@ -97,9 +120,12 @@ jobs:
record = {'commit': os.environ['COMMIT'],
'command': ['cargo', 'build', '--release', '--locked', '-p', 'coreav-cli', '--features', 'release-full'],
'coreav_sha256': sha('target/release/coreav'), 'lock_sha256': sha('Cargo.lock')}
Path(os.environ['RUNNER_TEMP'], 'shape-build.json').write_text(json.dumps(record))
root = Path(os.environ['RUNNER_TEMP'], 'shape-evidence')
root.mkdir()
(root / 'build.json').write_text(json.dumps(record))
PY
- name: Acquire and replay all registered shapes
id: acquire
run: |
set -euo pipefail
ORACLE_PATHS="$(python3 -I -B "$RUNNER_TEMP/oracle-owner/scripts/test_oracle.py" --resolve \
Expand All @@ -109,23 +135,29 @@ jobs:
echo "stage=oracle_qualification: invalid retained oracle pair" >&2
exit 1
fi
python3 tools/compat-corpus/github_shapes.py run --commit "$COMMIT" \
--build-record "$RUNNER_TEMP/shape-build.json" \
--coreav "$PWD/target/release/coreav" --ffmpeg "$FFMPEG" \
--pns-diagnostic "$PWD/target/release/examples/pns_diagnostic" \
--ffprobe "$FFPROBE" --x264 "$RUNNER_TEMP/oracle/x264" \
--bundle "$RUNNER_TEMP/shape-evidence" --scratch "$RUNNER_TEMP/shape-replay" \
--summary "$RUNNER_TEMP/shape-summary.json"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: github-shapes-evidence
path: |
${{ runner.temp }}/shape-evidence
${{ runner.temp }}/shape-summary.json
${{ runner.temp }}/shape-build.json
if-no-files-found: error
retention-days: 30
for REGISTRATION in github-shapes-200-pns-free github-shapes-200; do
ROOT="$RUNNER_TEMP/shape-evidence/$REGISTRATION"
mkdir "$ROOT"
python3 tools/compat-corpus/github_shapes.py run --commit "$COMMIT" \
--registration "$REGISTRATION" \
--build-record "$RUNNER_TEMP/shape-evidence/build.json" \
--coreav "$PWD/target/release/coreav" --ffmpeg "$FFMPEG" \
--pns-diagnostic "$PWD/target/release/examples/pns_diagnostic" \
--ffprobe "$FFPROBE" --x264 "$RUNNER_TEMP/oracle/x264" \
--bundle "$ROOT/bundle" --scratch "$RUNNER_TEMP/shape-replay/$REGISTRATION" \
--summary "$ROOT/summary.json"
done
printf '%s\n' '{"complete":true}' > "$RUNNER_TEMP/shape-evidence/completion.json"
- name: Keep acquisition evidence privately
if: always() && steps.acquire.outcome != 'skipped'
env:
R2_ENDPOINT: ${{ secrets.COREAV_CORPUS_R2_ENDPOINT }}
R2_ACCESS_KEY_ID: ${{ secrets.COREAV_CORPUS_R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.COREAV_CORPUS_R2_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ vars.COREAV_CORPUS_R2_BUCKET }}
run: |
python3 tools/compat-corpus/github_shapes_store.py --root "$RUNNER_TEMP/shape-evidence" \
--prefix "evidence/github-shapes-200-paired/$COMMIT/$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
aac-controls:
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -154,5 +186,7 @@ jobs:
COREAV_SHAPES_AAC_DIAGNOSTIC: ${{ github.workspace }}/target/release/examples/pns_diagnostic
run: |
python3 -I -m unittest discover -s tools/compat-corpus/tests -p test_github_shapes_aac.py
python3 -I -m unittest discover -s tools/compat-corpus/tests -p test_github_shapes_pns_free.py -v
python3 -I -m unittest discover -s tools/compat-corpus/tests -p test_github_shapes_store.py -v
python3 -I -m unittest discover -s scripts/tests -p test_aac_pns.py
python3 -I -m unittest discover -s scripts/tests -p test_aac_pcm_eligibility.py
2 changes: 2 additions & 0 deletions docs/agents/compat-corpus.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Corpus exclusions, compatibility and codec-coverage workflows with their candida

| Rule | Enforced by |
|---|---|
| A paired top-200 PNS acquisition distinguishes fixture encoding failures from diagnostic failures before any judged command starts | Separate generation and scan handlers emit closed failure labels in `github_shapes.run`; `test_all_generation_faults_stop_before_any_shape` injects both failures and proves neither can reach acquisition. An external encoder exit cannot be established by a type |
| The PNS registration describes the workflow's paired-only dispatch separately from the CLI's per-registration selection | The workflow's admission guard owns paired-only dispatch; `test_invalid_pair_selection_stops_before_checkout_or_media` executes its rejection and `test_paired_run_stops_on_pns_free_failure_and_keeps_results_private` checks the matching design statement. External workflow selection and English prose cannot share a declared type |
| Both exact and avc1-compatible top-200 copy comparisons preserve every packet's keyframe flag | `packet_rows` and `avc1_carriage` include the `K` flag in their compared rows. The keyframe-only regressions in `test_github_shapes.py` use complete packet records and assert the exact-path documents differ only in the selected flag. They reject both mismatch directions for first and later video and audio packets, while other flag bits stay outside this predicate. External probe records require runtime comparison, not a declared stream type |
| HEVC correctness shards retain the complete original roster and cannot count a partial, reordered or substituted part as complete | `corpus_shard` owns the deterministic assignment. `test_fixed_corpus_shards_cover_each_original_identity_once` proves the 54-file union without duplicates; `test_shard_completion_requires_its_exact_members_and_every_eof_arm` rejects missing, duplicate, reordered and changed identities and missing EOF arms. The workflow test requires all four non-fail-fast matrix entries and distinct artifact names |
| Metadata-only HEVC acquisition does not apply the complete-decoder acceptance predicate | The existing `packet_native` mode selects that predicate only for C2. `test_online_census_releases_each_owned_media_file_and_keeps_receipts` preserves metadata-only cleanup and false full-coverage flags on its two-file fixture; the complete-roster/EOF tests retain the 54-file C2 denominator. The command boundary owns runtime mode selection |
Expand Down
55 changes: 55 additions & 0 deletions docs/design/github-shapes-200-pns-free.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# GitHub Shapes 200 PNS-free registration

This registers `github-shapes-200-pns-free`, a separate measurement requested by the maintainer. It uses the [original registration](github-shapes-200.md), with only the fixture change and generation gate below. This document supplies a method, not results. No judged command or judged fixture generation runs before this registration and its tools merge.

## Purpose and unchanged scope

The original registration refuses exact credit for AAC-decoded output whose input contains perceptual noise substitution, or PNS. A separately registered fixture disables that encoder tool without changing CoreAV's AAC decoder or the output predicates. This isolates the fixture's effect on this generated representative. It does not establish decoder conformance or compatibility on other inputs.

The frozen roster, its digest, all 200 shapes and 1,470 repository-shape pairs stay unchanged. Instantiation, value and filter representatives, unresolved construction, denominators, outcome order, weights, exact decoded-output and copied-packet predicates, probe witnesses and replay rules are inherited unchanged. `compatible_aac` and `compatible_avc1` remain separate misses for the exact headline. The original registration and its retained results are not relabeled or replaced.

## Fixture recipe

Only command 0 of `tools/compat-corpus/github_shapes_fixtures.py` changes for the new registration. Insert `-aac_pns 0` immediately after `-c:a aac`:

```text
-f lavfi -i testsrc2=size=64x48:rate=10:duration=2 -f lavfi -i sine=frequency=440:sample_rate=48000:duration=2 -c:v libx264 -pix_fmt yuv420p -c:a aac -aac_pns 0 source.mp4
```

All other settings retain their defaults. The Matroska copy, concat list, PNG sequence and raw BGR24 remain derived from that source by the unchanged commands. The WAV, MP3, raw S16, PNG, JPEG and GIF recipes do not change. The original recipe's command list remains available unchanged under `github-shapes-200`.

## Generation gate and retained receipts

Before any judged command, scan the AAC in both `source.mp4` and `source.mkv` with the existing opt-in `pns_diagnostic` built by:

```sh
cargo build --locked --release -p coreav-aac --features diagnostics --example pns_diagnostic
```

Require a complete `coreav.aac-pns-diagnostic/1` scan under the existing `github_shapes_aac.noise_count` rules. Packet count must equal the frame-list length, every channel must be present, and the number of PNS bands must be zero. Independently require that packet count equals the pinned ffprobe's audio packet count. A container adapter may copy AAC into a diagnostic MP4 only if the complete ordered packet payloads and AAC configuration remain identical to the bound input. It must not decode or re-encode audio.

Any missing or failed scan, PNS band, incomplete channel or packet-count mismatch is `fixture_generation`. It voids the acquisition before any shape runs, rather than counting as an output miss. The bundle retains scan metadata, packet-count evidence, any adapter receipts, input digests, the diagnostic binary digest and its build command. The manifest binds those receipts and the selected registration. Replay independently repeats the scan on the bound fixtures and refuses missing, changed or nonzero-PNS evidence.

The per-command `exact_without_pns` guard stays unchanged. If it fails, that command remains `different`; passing the generation gate does not grant exact output credit.

## Paired acquisition

One main-only workflow dispatch selects both recipes at one clean merged main SHA. It acquires each recipe once in separate evidence directories using the same build and pinned programs. The original recipe is a pairing control, not a retry of an earlier acquisition. The workflow accepts only the paired selection. The CLI selects each registration explicitly, and every bundle and summary names its selected registration so evidence cannot be judged under the other recipe.

The host remains GitHub-hosted `ubuntu-24.04`, Linux x86-64. The build remains `cargo build --release --locked -p coreav-cli --features release-full`. FFmpeg 9.0.2, ffprobe and x264 retain the original pins and qualification. Build identities, dependencies, timeouts, fallback restrictions, program-start rules, accounting and failure handling stay unchanged. Failures remain misses. A replacement acquisition is allowed only for a recorded infrastructure or harness fault, with the failed evidence retained.

The method manifest additionally binds this design note. Tool-file digests change with implementation, as in the original registration's later method versions. Historical bundles remain replayable at their own measured commits, not under substituted method digests.

## Controls before merge

PR CI uses only independent controls, never the judged fixture generator or a command from the frozen roster. Encode a separate pink-noise control with the pinned encoder twice. Default settings must produce PNS bands; `-aac_pns 0` must produce none. Exercise the MP4 and Matroska gate paths. Mutation controls must reject one PNS band, an incomplete scan, missing channels, packet-count mismatch, changed adapter packets or configuration, missing receipts and a substituted registration. Each generation-gate failure must occur before a judged command can start.

## Order and evidence custody

1. Check the premise by counting PNS on the retained generated source from the completed original acquisition. This diagnostic judges no command. Stop if no PNS is found.
2. Commit this plan first, then the tools, workflow selection, generation gate, replay checks and controls in the same change.
3. Pass CI, independent review, exact-head similarity and the independent PNS controls before merge.
4. Dispatch the paired acquisition from main at one merged SHA, then replay each bound bundle.
5. Retain all acquisition evidence and summaries in restricted storage. No acquisition evidence, summaries or per-shape outcomes are uploaded as public workflow artifacts or printed in public logs. Credentials exist only in the workflow's retention step and never reach media child processes.

This change adds no public results page, README text, site text or documentation-index entry. Results are not announced and are not used in outward copy. Any separately retained comparison must name both fixtures and commits. A difference between them is a fixture effect, not a CoreAV improvement, a replacement for the registered coverage number or a claim about other inputs. Outcomes may fall as well as rise because the no-PNS PCM bar is stricter. Lossy encoded output still needs the unchanged exact predicate; removing PNS does not establish bit-identical AAC decode.
Loading
Loading