Vellum/docs/decisions
mithral fad0d7bc96 ADR-008: transcoding is optional, hardware-gated, off by default
ADR-002 decided never to transcode because the server is a headless,
GPU-less Xeon, and its measurements still hold. The problem is scope:
"this server cannot transcode" became "Vellum does not transcode", and
only the first is forced by the hardware.

Intel Quick Sync has been in most desktop CPUs since 2015, NVENC is in
every recent Nvidia card, and VAAPI covers AMD and Intel on Linux. Capping
the product at the hardware in one closet is the wrong constraint, and the
gap is visible: a client that cannot decode HEVC gets nothing, and in
Chrome that is not even a clean refusal - the video never decodes and
audio plays over a blank frame.

So the engine is added and its registration is gated:

- registered only when usable transcode hardware AND ffmpeg are both present
- off by default; direct play stays the default and the preference
- consulted only when no other engine can direct-play the file, which is
  exactly the case that returns "no engine can play this" today
- hardware-accelerated only. No CPU fallback: that is the stall ADR-002
  measured, and it fails slowly, which is worse than refusing.

This deployment is unchanged. On a GPU-less Xeon the engine is never
registered and the path is never reached, so ADR-002 holds as written.
ADR-002's status now points here rather than being deleted, per the rule
that a changed decision gets a new record instead of an edited one.
2026-10-12 01:14:37 -04:00
..
ADR-001-sqlite-with-a-seam.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-002-direct-play-only.md ADR-008: transcoding is optional, hardware-gated, off by default 2026-10-12 01:14:37 -04:00
ADR-003-mark-missing-never-delete.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-004-modular-monolith.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-005-one-item-access-chokepoint.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-006-table-backed-job-queue.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-007-fixed-width-timestamps.md Documentation, and make a fresh clone actually work 2026-10-12 00:18:11 -04:00
ADR-008-optional-hardware-transcoding.md ADR-008: transcoding is optional, hardware-gated, off by default 2026-10-12 01:14:37 -04:00
README.md ADR-008: transcoding is optional, hardware-gated, off by default 2026-10-12 01:14:37 -04:00

Decisions

Each record captures a decision that was expensive to reverse, the alternatives that were rejected, and the reasoning. They exist so nobody has to re-litigate a settled question — and so an agent does not "improve" something that was deliberate.

Read the ones relevant to what you are changing.

ADR Decision Rejected alternatives
001 SQLite, with a storage seam for later PostgreSQL; fixing the write lock in code instead
002 Direct play only, never transcode On-demand CPU transcode; remux; pre-transcode
003 A vanished file is marked, never deleted Delete on scan; auto-purge; keep it invisible
004 One binary with enforced package boundaries Microservices; unenforced conventions
005 One item-access chokepoint, internal/catalog Leave the duplication; a shared helper; a generic repository
006 The job queue is a table Redis or a broker; in-memory goroutines
007 Fixed-width timestamps via core.Stamp Integer nanoseconds; six/nine digits; sorting in Go
008 Transcoding is optional, hardware-gated, off by default Keeping never-transcode as a product rule; CPU fallback; transcode by default

Writing a new one

Add ADR-00N-short-title.md with Status, Date, Context, Decision, Alternatives Considered (with the reason each was rejected) and Consequences. Do not delete an ADR when a decision changes — write a new one that supersedes it, so the history stays readable.

Two things make an ADR worth writing: the decision would be expensive to reverse, and a reasonable person could have chosen differently. If neither is true, a comment in the code is the right place.