GIT-AV — VERSION CONTROL FOR POST-PRODUCTION

git-av

A content-addressable, branchable, structurally-diffable, provenance-tracking, NLE-agnostic version control system for audio-video post-production. Like git for media: sub-second branch switching via symlink swizzling, blake3 vault, OpenTimelineIO domain-split, and C2PA v2.2 provenance — all from a single 8.1 MB Rust binary.

VERSION0.4.0-dev (S8)
UPDATED2026-05-12
STATUSS8 shipped — v0.4 GA at S10

Sub-Second Branch Switching

Atomic symlink swizzle: ~14 ms for 100-file checkout (debug). The media bytes never move — only the pointers flip. Cross-platform: macOS, Linux, Windows developer mode.

Application-Agnostic Timeline

OpenTimelineIO split into six per-domain JSON blobs — cuts, color, audio, effects, markers, metadata. Colorists and sound designers edit independent files; three-way merge is per-domain.

C2PA Built-In

Every snapshot auto-generates a C2PA v2.2 manifest (c2pa-rs 0.82). EU AI Act Article 50 disclosure surfaces in the audit; PDF export ships compliance-ready.

What it does today
CapabilityWhere it livesSprint
Content-addressable sharded vault (blake3 + 0o444 read-only blobs)crates/gav-core/src/vault.rsS1
Atomic symlink swizzle (sub-second checkout, cross-platform)crates/gav-core/src/symlink.rsS1
SQLite ledger (rusqlite + bundled, WAL, FKs ON)crates/gav-core/src/ledger.rsS2
Branch manager (create/delete/list/checkout/compare, parent-chain walks)crates/gav-core/src/branch.rsS2
C2PA v2.2 generation (auto on snapshot/revert), verify, inspect, auditcrates/gav-core/src/c2pa/S3
OTIO import/export + domain split (6 blobs + manifest, per-domain versioning)crates/gav-timeline/src/domain/S4
Timeline validator (V1–V10 rule engine), diff (per-domain), three-way mergecrates/gav-timeline/src/{validate,diff,merge}.rsS4
JSON-RPC 2.0 + WebSocket events + REST blob streaming (gav serve)crates/gav-server/S5
Tauri 2 desktop shell with in-process server embedapps/desktop/S6–S6.1
Timeline Diff view (split-player, 7-domain diff list, CMX 3600 EDL export)apps/web/src/views/timeline-diff/S7
AAF change-list export (capability-gated via --features aaf-python)crates/gav-timeline/scripts/render_aaf.pyS7.5
Branch Graph view (React Flow + dagre, click-to-swizzle, CommitDrawer)apps/web/src/views/branch-graph/S8
Provenance Inspector (virtualized grid, sort+filter, Article 50 PDF export)apps/web/src/views/provenance/S8
c2pa.audit/v3 server-side sort (4 keys) + filter (4 axes), cursor pinned to sortcrates/gav-core/src/ledger.rs audit_pageS8
Resilience gate — end-to-end CLI test, no daemon, no GUItests/cli/full_workflow.shevery sprint
Why it exists

Post-Production Runs on Filenames

Project_v17_FINAL_FINAL_v2_colorist.drp. Universally hated, universally used. The canonical record of "what changed between two states of this project" doesn't exist as a structured artifact — it exists as memory, manual change lists, and tribal tooling.

Tribal Tooling Doesn't Talk

Avid FilmScribe, Resolve ColorTrace, EdiLoad / Conformalizer / Matchbox in the sound suite — each exports a flat-text artifact in a domain-specific format. None are visible to a producer who doesn't have the corresponding NLE installed.

What Software Solved Twenty Years Ago

What git diff solved for code in 2005, post-production has not solved in 2026. The closest analog — vit (697☆) — works only against DaVinci Resolve project files. It validates the bet's shape; it does not close the gap.

Two failure modes git-av rejects

The "shared-storage workflow" approach (DaVinci Resolve Project Server, Avid Nexis bin-locking): excellent for live multi-user editing within one tool, but offers no history, no diff, no provenance, and no cross-NLE visibility. A producer without the NLE installed cannot see what changed. The "rendered-pixel diff" approach (Frame.io v4 Comparison Viewer): diffs the picture, not the structure. Complementary but not equivalent — it tells you the rough cut looks different; it doesn't tell you cut 14 was trimmed 12 frames and reel 2's grade was reset.

Architecture
Rendering diagram…

Press a to expand, Esc to collapse, \ to cycle themes, 1/2/3 for tabs. Five more diagrams on the Diagrams tab.

The three keystone views

The discipline of three views, no more — every view is a permanent maintenance cost, and the scope-fence kept S6 through S8 shipping on cadence. All three are reachable as gav <cmd> --json from the CLI and as /timeline-diff, /branch-graph, /provenance in the web/desktop shell.

Timeline Diff

S7CMX 3600AAF (S7.5)

Split-player with synced playback comparing two refs; structured change list across seven domains; conflict callouts; CMX 3600 EDL with --handles N for crossfade edge.

AAF export is capability-gated — requires --features aaf-python + pyaaf2 ≥ 1.6 in the reachable Python environment.

Branch Graph

S8React Flowdagre

Decision-tree visualization of branch lineage with deterministic OKLCH 21-bucket palette; click-to-swizzle optimistic checkout; List View shadow with j/k/Enter// keyboard nav; CommitDrawer @ 40px virtualized.

Click-to-swizzle relies on TanStack onSettled invalidation today; a WebSocket branch.updated push would collapse into the same query keys.

Provenance Inspector

S8c2pa.audit/v3Article 50

Virtualized 1000+ row asset grid; 300 ms-debounced filter chips; sticky Article 50 compliance summary (GREEN / AMBER / RED); JSON + PDF export from the same RPC.

100k-row server-side perf gate is documented as a known follow-up — current testing is manual; CI automation deferred to S8.x.

Who it's for
RoleWhat git-av does for them
Picture editor (Premiere / Avid / FCP / Resolve cut page)Structural diff list using Avid-cultural verbs (trimmed / extended / slipped / moved); CMX 3600 export for downstream conform.
Producer / executive (no NLE installed)The web /timeline-diff route — synced split-player + thumbnail strip + change list. The gap-fill nobody else ships.
Assistant editorAutomated change-list as a build artifact instead of a two-hour manual write-up.
Colorist (Resolve color page)ColorChange domain + AAF export with grade nodes. "Did my grade survive the recut?" answered before opening Resolve.
Sound editor / re-recording mixer (Pro Tools, Logic, Nuendo)CMX 3600 with --handles N for crossfade edge; AAF in S7.5 — the deciding feature for sound-stage adoption.
VFX coordinator / supervisorMediaChange::SourceReplaced rows surface vfx_023_v04 → v05 turnover automatically — currently a manual spreadsheet at every facility.
DI / online finishingCMX 3600 + AAF + MediaChange::SourceMissing warnings before export.
Compliance / broadcast QCProvenance Inspector + C2PA chain + Article 50 PDF audit.
AI agents / CI pipelinesEvery UI feature reachable as gav <cmd> --json; OpenRPC schema published.
The CLI surface

CLI parity is the contract. Anything the GUI shows, the CLI prints. Anything the GUI can do, the CLI can do — including --json output that round-trips through the same outcome structs. The resilience gate tests/cli/full_workflow.sh is the canonical integration test; no daemon, no GUI required.

Project & status
gav initCreate .gav/ repo (vault, manifests, refs, ledger, c2pa cert)
gav statusSchema status/v2 — stale files + c2pa summary
gav log [-n N]Branch-wide history
gav schemaOpenRPC document (24 methods)
Version control
gav snapshot FILE -m MSGStore + version + auto-C2PA when enabled
gav revert FILE [ref] [--list]Revert to a prior version
gav diff FROM TOVault-layer per-file diff between two refs
gav branch [NAME] [--from] [-d|-D]Create / list / delete branches
gav checkout NAMEAtomic symlink swizzle to target branch
C2PA provenance
gav c2pa generate HASH--source-type --license --force
gav c2pa verify HASHExits non-zero on valid=false
gav c2pa inspect HASHManifest detail + ingredient DAG
gav c2pa audit--sort {hash|manifested|signature|ai_disclosed}
--filter-signature {signed|unsigned|invalid}
--filter-manifested / --filter-unmanifested
--filter-ai / --filter-non-ai
gav c2pa audit --pdf FILEArticle 50 disclosure PDF (printpdf 0.9.1, A4, core fonts)
--article-50-only --include-unmanifested --title
gav c2pa statusPer-blob manifest state summary
Timeline (S4–S7.5)
gav timeline import FILE [--no-split]OTIO → 6 per-domain JSON blobs + manifest, each snapshotted + manifested
gav timeline export MANIFEST [-o FILE]Reassemble OTIO from the six domain blobs
gav timeline diff MANIFEST FROM TO--edl FILE --aaf FILE --handles N --title --frame-rate
gav timeline validate [MANIFEST] [--strict]Exits 0/1/2 clean / warnings / errors
gav timeline merge MANIFEST FROM--strategy auto|ours|theirs — exits 1 on conflict
Server (S5)
gav serve--bind --repo --no-auth --token --cors-origin --print-token
POST /rpc24 JSON-RPC 2.0 methods (bearer-token auth)
WS /wsWebSocket event bus (branch.updated, etc.)
GET /blob/<hash>REST blob stream with C2PA verify-default
Roadmap

S9 — Packaging

Signed .dmg / .msi / AppImage via tauri-action@v0; Cloudflare R2 auto-updater; bundle-size CI gates. Local pnpm tauri build already produces working bundles (8.1 MB .dmg smoke-tested). Deferred pending three operational decisions: code-signing budget (~$219/yr), R2 + DNS provisioning, GitHub Actions secrets.

S10 — LAN polish + v0.4 GA

Capability atom + producer-tablet capability gating; touch-target spacing (@media (pointer: coarse) → 44×44 px); mDNS advertise (_gav._tcp.local); GAV012 deployment-guide finalization; full README rewrite. Tag is v0.4.0 — no sprint suffix.

S11+ — v0.5 sync

gav remote + gav push + gav pull — multi-vault sync to a remote gav-server. Wire-protocol scoping (custom JSON-RPC vs git smart-HTTP vs WebSocket delta) is itself a sprint of design work. NLE auto-snapshot hooks (Resolve/Premiere/FCP/Avid) and CAI-issued production C2PA certs land here too.

Product principles
  • Resilience first. The CLI works without the server. The server works without the GUI. The GUI works without an internet connection. Every layer is independently usable.
  • CLI parity, always. Every GUI feature reachable as gav <cmd> --json. AI agents and CI pipelines are first-class consumers, not afterthoughts.
  • Vocabulary editors already speak. "V14 → V15", "trimmed / slipped / moved / rippled", "Picture / Media / Color / Audio / Effects / Markers / Metadata". Not "ref:main@a1b2c3".
  • Structural diff works without proxies. No video file → thumbnail strip + change list still works. Sound mixers prefer this mode.
  • Triple-encoding for accessibility. Severity = color + icon + aria-label. WCAG 1.4.1 across every domain row, every signature badge.
  • Frame budget discipline. Vsync-rate UI (scrubber, playhead, sync indicator) uses useRef + rAF. React state is reserved for the list. setState in a 16 ms loop is non-shippable.
  • The change list is the page; the player is the proof. Editors scan the list first, then play the segment that interests them. Lead with the DiffList in any UX decision.
  • Self-signed is acceptable; trusted is the upgrade path. v0.4 ships with a working test cert that produces structurally valid manifests; CAI procurement is a one-page section in GAV012. Studios swap the cert when they want trusted.
  • No backwards-compatibility shims pre-1.0. Schema bumps happen freely (the audit cursor went v2 → v3 in S8 with no migration). Pre-GA users don't exist. Post-v1.0 will be different.
  • One commit per task, never batch. Sprint cadence + per-task commit + per-sprint report + per-sprint tag. The audit trail is the project.