Development¶
afmpeg follows spec-driven development: no implementation change without a spec it implements. The specs are the authoritative decision record; the code is downstream of them.
Picking up implementation? Start at the implementation roadmap — the phased build order across all specs (0013–0034) with dependencies and prerequisites, and its Pick-up menu of the remaining trigger-gated work. Phases 0–4 are shipped (through vocab v9 — job progress), and Phase 5 (the native backend + matrix, HEVC/AV1, perf) is largely shipped too. Current anchors: afmpeg v0.11.2 (plus
0034onmain, unreleased), ffmpeg-wasi n8.1.2-11. What remains is all optional/trigger-gated —0009CLI,0030WASM threads, arm64/darwin native, HW-accel encode,0025/0026.
Contributor docs¶
- CI security scanning — how the MR security gate works (govulncheck / osv-scanner / trivy / gitleaks), and the recorded decisions behind the osv-scanner ignore + job overrides (incl. the unfixable, unreachable x/crypto advisory).
Specs¶
The source of truth. They live in the project wiki — see the register for all of them, in number order, with their current status.
Start with 0001-afmpeg, the thesis; it decomposes into the
component specs.
They moved out of docs/ because a spec is a point-in-time decision record: read
for the conclusion it reached, not kept true as the code changes. docs/ holds only
what does change with the code.
| Also | Scope |
|---|---|
| external review — validation & disposition | The commissioned external review + our per-finding validation verdicts and spec mapping |
Method¶
- Spec first. Get a spec to
APPROVED, then implement against it test-first. New specs claim the next number from the register and are published to the wiki asspecs/NNNN-<slug>, not committed to this repository. - Library before CLI. Logic lives in
pkg/; any command layer is a thin adapter. - Test-first from the spec's contracts, table-driven with
t.Parallel(); the per-package coverage bar is ≥90% on newpkg/code. - Every package carries a
doc.go. The package-level documentation lives in a dedicateddoc.go(not scattered above a random file'spackageclause), so the package's purpose is discoverable in one place and onpkg.go.dev. - Docs land with the code, not after. A change that adds or reshapes a component ships its Diátaxis documentation in the same MR — an explanation page for a new component, a how-to for a new task, reference for a new config/CLI surface. Docs are part of "done", never an afterthought.
- Verify before PR:
just ci(tidy, generate, test, race, lint).
Local workflow¶
just # build (tidy + generate + CGO_ENABLED=0 build)
just test # unit tests with coverage
just test-race # race detector
just lint # golangci-lint
just ci # the full local gate
just docs-serve # preview this site
Integration test (real ffmpeg)¶
The runtime has a gated integration test that loads a real ffmpeg-wasi module and transcodes in memory. It skips unless pointed at a module:
The runtime provides the env setjmp/longjmp host module and the WebAssembly feature set a
real FFmpeg build needs (spec 0004 R-0004-9), so a released
ffmpeg-wasi engine (spec
0007) loads and runs.