Pelorus is the GPU pre-encode sibling of vmafx and follows the same engineering contract. Read AGENTS.md and docs/principles.md before opening a PR.
- Branch + PR. Never commit to
master; never force-push it. Squash or fast-forward merge only. - Conventional Commits.
type(scope): subject. Types:feat, fix, perf, refactor, docs, test, build, ci, chore, revert.!/BREAKING CHANGE:for breaks. Branches:type/<slug>. - Local gate before pushing. Run
make verify-native. If the pinned Praetor engine is installed, also runmake verify-all; see Governance and agent contexts below. - Lint-clean touched files. Every file your PR touches leaves the tree
warning-clean to
-Wall -Wextra -Werrorand clang-tidy. A// NOLINTneeds an inline citation (ADR / research digest / load-bearing invariant).
These mirror vmafx's rules; reviewers verify them.
- ADR for any non-trivial architectural / policy / scope decision —
docs/adr/NNNN-kebab.md, Nygard format, landed before the implementing commit. Runscripts/adr/next-free.sh --claim <slug>to reserve the number. Cite the user request (req) or popup answer (Q<r>.<q>) in## References. - Per-surface docs — any user-discoverable surface (a filter, an AVOption,
a public
libpelorusAPI, an interop section, ameson_options.txtflag) ships human-readable docs underdocs/in the same PR. No docs = unmergeable. See docs/adr/0100-doc-substance-rule.md. - Six deep-dive deliverables for fork-local PRs — research digest,
decision matrix (the ADR's alternatives table),
AGENTS.mdinvariant note, reproducer command in the PR body,changelog.d/<section>/<topic>.mdfragment, and adocs/rebase-notes.mdentry when the change affects the FFmpeg patch stack. See docs/adr/0108-deep-dive-deliverables-rule.md. - Patch-stack sync — a change to any
libpelorussurface the FFmpeg patches consume updatesffmpeg-patches/files/+ the regenerated patch in the same PR, verified by a full series replay (FFMPEG_REPO=/absolute/path/to/ffmpeg ffmpeg-patches/test/build-and-run.sh). The replay applies the shared FFmpeg fix series first. A fix to a stock FFmpeg file that carries no Pelorus name goes to VMAFx/ffmpeg-patches, not into this stack (ADR-0185).
AGENTS.md is the canonical cross-tool repository guide. Reviewer personas
under .agents/agents/ are canonical too. Generated cross-tool contexts include
root CLAUDE.md, editor/agent projections, and persona copies; do not edit them
directly. Paperclip's separately generated harness/rules pair needs explicit
consumer reconciliation. The complete ownership map, target composition,
baseline semantics, and failure triage are in
docs/development/build.md.
A clean clone needs Go 1.27, Node.js 22.12 or newer for the documentation gate, and the exact Praetor engine pin used by CI:
go install github.com/cordanaLLM/praetor/cmd/standardsctl@2d23b292417386fe8259da29690266ce331062c6
export PATH="$(go env GOPATH)/bin:$PATH"
go version -m "$(command -v standardsctl)" | grep -F 6622361940dcstandardsctl version names the build commit, and the module
pseudo-version that go version -m prints names it too; CI checks both. The pin
installs a binary named standardsctl. Praetor's own text, including the
generated README block, calls the same program praetorctl. The Makefile
and the Lefthook jobs do not use the binary on PATH: they run the pinned
commit through .config/lefthook/engine.sh, which installs it on first use.
The agent hooks call it by the name praetorctl only. If you run Claude Code,
Codex, or Gemini CLI in this repository, put a copy under that name next to
the installed binary:
cp "$(go env GOPATH)/bin/standardsctl" "$(go env GOPATH)/bin/praetorctl" # Windows: standardsctl.exe to praetorctl.exe.claude/settings.json, .codex/hooks.json, and .gemini/settings.json run
praetorctl hook <client> pre-tool before every agent shell command. It blocks
commands that would skip or remove Git hooks (such as --no-verify) and
allows the rest. Without praetorctl on PATH the hook fails with a
command-not-found error that Claude Code and Gemini CLI report without blocking,
so agent commands then run without that policy. The development guide has the
rule list, a smoke test, and the Windows notes.
make compile-context # regenerate vendor projections
make compile-context-verify # reject projection drift
make audit # apply the pinned HISS baseline ratchet
make docs-lint docs-figures # locked Markdown and figure checks
make verify-all # context + audit + native Pelorus gate + docs gateThe manifest declines no adoption step
(ADR-0153), so a local audit
requires the Lefthook pre-commit hook (make hooks-install) and, when it finds
a forge token, compares the live master protection with the committed
ruleset. That comparison fails until the maintainer applies the ruleset;
make audit AUDIT_FLAGS=--offline skips it, and CI has no token. Every other
audit check must pass. Do not create a placeholder hook file, weaken the
manifest, or run remote sync to get past a failing check.
The audit also reads two lists that a code change can break. Every hosted
meson setup passes --werror, because the audit does not read Meson's
default_options. Every C file the Meson build compiles is listed in
.config/clang-tidy/lane-files.txt, which make tidy and the core job lint;
a new unit that is not listed fails the audit
(ADR-0168).
The hosted job also compares your branch with its target. The recorded baseline total may not grow unless the increase carries a recorded reason, and the baseline must record every current finding at its current line. The exact commands, their local equivalents, and what each one allows are in the development guide.
make hooks-install stays opt-in: it installs the tracked Lefthook hooks
into the Git hooks directory that every linked worktree shares. A commit then
runs the context check and two offline audits; a push runs the audit, the
flavor audit, the Praetor gate, and make verify-all. lefthook.yml sets
no_auto_install, so rerun make hooks-install after it changes. CI does not
install Git hooks, apply the ruleset, or run remote Praetor sync; the
maintainer applies .github/rulesets/main.json with praetorctl sync --remote.
Adoption does register the agent pre-tool hook above in the tracked client
settings. The development guide covers the hooks, the ruleset, and the dev
container (.devcontainer/).
The PelorusSideData interop ABI is append-only (interop.h R1/R2). Adding
a field or section bumps PELORUS_ABI_MINOR and adds a case to the shared
conformance fixture (libpelorus/test/interop_test.c). A breaking change is
forbidden — mint a new section bit instead. See
docs/adr/0103-interop-sidedata-abi.md.
Ten of the libpelorus files are mirrored by VMAFx; changing one follows the mirror contract.
A contribution falls under the licence of the file it changes; a file says
which in its SPDX-License-Identifier line or, without one, in
REUSE.toml (ADR-0171,
docs/licensing.md):
-
A new file, or a change to a Pelorus file: EUPL-1.2, a reciprocal licence. By contributing you license your contribution under the EUPL-1.2. A new C, shell or Python file starts with the copyright line and the SPDX line, in the comment syntax of its language:
/* * Copyright 2026 Lusoris * * SPDX-License-Identifier: EUPL-1.2 */
Name yourself in the copyright line of a file you create; files without a header of their own are covered by
REUSE.toml. -
A file the patch stack adds to FFmpeg (
ffmpeg-patches/files/, and a test built inside the FFmpeg tree): LGPL-2.1-or-later, with FFmpeg's LGPL header, so the file can join FFmpeg. -
Vendored files (
.claude/skills/superpowers/,tools/figures/third_party/): their upstream licence. Change them only by re-vendoring.
A new file that needs other terms gets a table in REUSE.toml, after the
whole-tree default. reuse lint (the reuse-lint pre-commit job and the
REUSE lint CI check) must pass.
Every commit carries a sign-off: git commit -s appends
Signed-off-by: Your Name <you@example.org>. It states, under the
Developer Certificate of Origin 1.1, that
you wrote the change or have the right to submit it under the licence of the
files it touches. There is no contributor licence agreement. Bot commits
(Renovate) are exempt. The commit-msg Lefthook job (installed with make hooks-install) checks the trailer locally, and the Standards workflow checks every pull request commit in its "Verify DCO sign-off" step, so an unsigned commit fails the pull request.