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.
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.
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.
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.
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.
| Capability | Where it lives | Sprint |
|---|---|---|
| Content-addressable sharded vault (blake3 + 0o444 read-only blobs) | crates/gav-core/src/vault.rs | S1 |
| Atomic symlink swizzle (sub-second checkout, cross-platform) | crates/gav-core/src/symlink.rs | S1 |
| SQLite ledger (rusqlite + bundled, WAL, FKs ON) | crates/gav-core/src/ledger.rs | S2 |
| Branch manager (create/delete/list/checkout/compare, parent-chain walks) | crates/gav-core/src/branch.rs | S2 |
| C2PA v2.2 generation (auto on snapshot/revert), verify, inspect, audit | crates/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 merge | crates/gav-timeline/src/{validate,diff,merge}.rs | S4 |
| JSON-RPC 2.0 + WebSocket events + REST blob streaming (gav serve) | crates/gav-server/ | S5 |
| Tauri 2 desktop shell with in-process server embed | apps/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.py | S7.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 sort | crates/gav-core/src/ledger.rs audit_page | S8 |
| Resilience gate — end-to-end CLI test, no daemon, no GUI | tests/cli/full_workflow.sh | every sprint |
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.
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 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.
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.
Press a to expand, Esc to collapse, \ to cycle themes, 1/2/3 for tabs. Five more diagrams on the Diagrams tab.
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.
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.
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.
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.
| Role | What 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 editor | Automated 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 / supervisor | MediaChange::SourceReplaced rows surface vfx_023_v04 → v05 turnover automatically — currently a manual spreadsheet at every facility. |
| DI / online finishing | CMX 3600 + AAF + MediaChange::SourceMissing warnings before export. |
| Compliance / broadcast QC | Provenance Inspector + C2PA chain + Article 50 PDF audit. |
| AI agents / CI pipelines | Every UI feature reachable as gav <cmd> --json; OpenRPC schema published. |
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 init | Create .gav/ repo (vault, manifests, refs, ledger, c2pa cert) |
| gav status | Schema status/v2 — stale files + c2pa summary |
| gav log [-n N] | Branch-wide history |
| gav schema | OpenRPC document (24 methods) |
| Version control | |
|---|---|
| gav snapshot FILE -m MSG | Store + version + auto-C2PA when enabled |
| gav revert FILE [ref] [--list] | Revert to a prior version |
| gav diff FROM TO | Vault-layer per-file diff between two refs |
| gav branch [NAME] [--from] [-d|-D] | Create / list / delete branches |
| gav checkout NAME | Atomic symlink swizzle to target branch |
| C2PA provenance | |
|---|---|
| gav c2pa generate HASH | --source-type --license --force |
| gav c2pa verify HASH | Exits non-zero on valid=false |
| gav c2pa inspect HASH | Manifest 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 FILE | Article 50 disclosure PDF (printpdf 0.9.1, A4, core fonts)--article-50-only --include-unmanifested --title |
| gav c2pa status | Per-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 /rpc | 24 JSON-RPC 2.0 methods (bearer-token auth) |
| WS /ws | WebSocket event bus (branch.updated, etc.) |
| GET /blob/<hash> | REST blob stream with C2PA verify-default |
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.
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.
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.
gav <cmd> --json. AI agents and CI pipelines are first-class consumers, not afterthoughts.useRef + rAF. React state is reserved for the list. setState in a 16 ms loop is non-shippable.trusted.