Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
60fde9e
Remove bundle runtime while preserving ordinary Git transfer
tobi Sep 11, 2026
bf65c01
Add exact pack coverage snapshots and durable retirement authority
tobi Sep 11, 2026
72b5e07
Add conserving staged pack lifecycle and verified multi-pack bitmaps
tobi Sep 12, 2026
4ff4f7a
Deliver proven packs through native Git URI negotiation
tobi Sep 12, 2026
40d0899
Check bounded publication contracts and correct ambiguous receipts
tobi Sep 12, 2026
ff82208
Validate cache evidence and preserve proven readiness
tobi Sep 12, 2026
d9ed2a6
Prove indexed conservation and current tips before final retirement
tobi Sep 12, 2026
40bdb45
Install ripgrep for the bounded contract CI job
tobi Sep 12, 2026
f22aeed
Merge branch 'packfiles/05-contract-validation' into packfiles/06-clo…
tobi Sep 12, 2026
4669b96
Merge branch 'packfiles/06-closure-cache' into packfiles/07-seal-evid…
tobi Sep 12, 2026
e44485e
Isolate rebuild locks and synchronize same-base push contenders
tobi Sep 12, 2026
cad3bb9
Merge branch 'packfiles/01-remove-bundles' into packfiles/02-coverage…
tobi Sep 12, 2026
bf32cc4
Merge branch 'packfiles/02-coverage-foundations' into packfiles/03-co…
tobi Sep 12, 2026
1b92352
Merge branch 'packfiles/03-conserving-lifecycle' into packfiles/04-ur…
tobi Sep 12, 2026
82b334a
Merge branch 'packfiles/04-uri-delivery' into packfiles/05-contract-v…
tobi Sep 12, 2026
d4f7599
Merge branch 'packfiles/05-contract-validation' into packfiles/06-clo…
tobi Sep 12, 2026
f975556
Merge branch 'packfiles/06-closure-cache' into packfiles/07-seal-evid…
tobi Sep 12, 2026
fc4ce3d
Exercise standalone smoke and serial fault simulations in CI
tobi Sep 12, 2026
c379d97
Merge branch 'packfiles/03-conserving-lifecycle' into packfiles/04-ur…
tobi Sep 12, 2026
fe4930c
Merge branch 'packfiles/04-uri-delivery' into packfiles/05-contract-v…
tobi Sep 12, 2026
05cf095
Merge branch 'packfiles/05-contract-validation' into packfiles/06-clo…
tobi Sep 12, 2026
f3998bc
Merge branch 'packfiles/06-closure-cache' into packfiles/07-seal-evid…
tobi Sep 12, 2026
72daddd
Describe verification gaps without internal issue identifiers
tobi Sep 12, 2026
15d6095
Merge branch 'packfiles/05-contract-validation' into packfiles/06-clo…
tobi Sep 12, 2026
9d0ec0a
Merge branch 'packfiles/06-closure-cache' into packfiles/07-seal-evid…
tobi Sep 12, 2026
5166312
Merge pull request #52 from tobi/packfiles/01-remove-bundles
tobi Sep 12, 2026
85990b6
Merge pull request #53 from tobi/packfiles/02-coverage-foundations
tobi Sep 12, 2026
651d64c
Merge pull request #54 from tobi/packfiles/03-conserving-lifecycle
tobi Sep 12, 2026
50bbed2
Merge pull request #55 from tobi/packfiles/04-uri-delivery
tobi Sep 12, 2026
392a3c0
Merge pull request #56 from tobi/packfiles/05-contract-validation
tobi Sep 12, 2026
95abf48
Merge pull request #57 from tobi/packfiles/06-closure-cache
tobi Sep 12, 2026
80e9a20
Merge pull request #58 from tobi/packfiles/07-seal-evidence
tobi Sep 12, 2026
054f985
chore: merge upstream/main into the fork
yordis Sep 13, 2026
5bda1e7
ci(spec): pin the contract job's actions to commit SHAs
yordis Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,33 @@ jobs:
- name: Build the SPA and the SDK
run: just web-build
- run: just e2e
- run: just sim
- run: just smoke

# publish-canary needs this job, so its verdict decides whether a main commit is published:
# a moving tag here could pass a contract that did not hold. Pinned like the publishing job,
# for the same reason, even though this job itself holds nothing but a read token.
spec:
name: bounded contract checks
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Install spec runner dependencies
run: sudo apt-get update && sudo apt-get install -y ripgrep
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4.9.1
with:
distribution: temurin
java-version: 21
- uses: taiki-e/install-action@e67fa11c4b9316fa714ddf0abed07a0c3143b95b # v2.87.4
with:
tool: just
- run: just spec
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: spec-evidence
path: target/test-logs/spec-*
Comment thread
cursor[bot] marked this conversation as resolved.

# Canary image publish. Lives in this workflow, not a separate one, so `needs` gates it on the
# same green run that just tested the commit: a red main never produces a canary tag, and there
Expand All @@ -101,7 +128,7 @@ jobs:
# at a digest nobody chose. A re-run moves `canary` only; the sha- tag is written once, ever.
publish-canary:
name: publish canary image
needs: [build-test, e2e]
needs: [build-test, e2e, spec]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
Expand Down
225 changes: 154 additions & 71 deletions AGENTS.md

Large diffs are not rendered by default.

55 changes: 6 additions & 49 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ members = [
"crates/walgit-git",
"crates/walgit-wal",
"crates/walgit-server",
"crates/walgit-bundle",
"crates/walgit-cli",
]

Expand Down Expand Up @@ -67,7 +66,6 @@ walgit-config = { path = "crates/walgit-config" }
walgit-git = { path = "crates/walgit-git" }
walgit-wal = { path = "crates/walgit-wal" }
walgit-server = { path = "crates/walgit-server" }
walgit-bundle = { path = "crates/walgit-bundle" }

anyhow = "1"
thiserror = "2"
Expand Down Expand Up @@ -131,7 +129,6 @@ hex = "0.4"
humantime = "2"
humantime-serde = "1"
bytesize = { version = "2", features = ["serde"] }
cron = "0.15"
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1", features = ["v4"] }
dashmap = "6"
Expand Down
8 changes: 4 additions & 4 deletions Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# -v walgit-cache:/var/lib/walgit \
# walgit
#
# The image carries git (upload-pack, repack, bundle, index-pack run as subprocesses),
# git-lfs, CA certificates and tini. Config comes from /etc/walgit/walgit.toml or
# The image carries git (upload-pack, repack, index-pack run as subprocesses),
# git-lfs, GNU coreutils (bounded sort/comm), CA certificates and tini. Config comes from /etc/walgit/walgit.toml or
# WALGIT__SECTION__KEY environment overrides; the local cache (materialized repositories,
# a self-signed TLS cert) lives under /var/lib/walgit and can be wiped at any time — the
# bucket is the only durable state. `nix build .#image` produces the same thing from flake.nix.
Expand Down Expand Up @@ -42,10 +42,10 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
&& install -D target/release/walgit-server /out/bin/walgit-server

# ---- 3. runtime -----------------------------------------------------------------------------
# trixie ships git 2.47+: walgit wants >= 2.47 on the server (pack.writeReverseIndex, bundle-uri,
# trixie ships git 2.47+: walgit wants >= 2.47 on the server (pack.writeReverseIndex,
# `index-pack --rev-index`); clients need >= 2.46.
FROM docker.io/library/debian:trixie-slim
RUN apt-get update && apt-get install -y --no-install-recommends git git-lfs ca-certificates tini curl \
RUN apt-get update && apt-get install -y --no-install-recommends git git-lfs coreutils ca-certificates tini curl \
&& rm -rf /var/lib/apt/lists/* \
&& git --version
RUN useradd --uid 1000 --create-home --shell /bin/sh walgit \
Expand Down
19 changes: 10 additions & 9 deletions GOAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,22 @@ anyone can run against a bucket, and predictable enough that tooling can build o
3. **Fast for the monorepo, from machines smaller than it.** A repository of tens of gigabytes, tens of
millions of objects and hundreds of thousands of refs must be *fast* from a host with a few GiB of tmpfs:
refs in < 1 s cold, web pages in ~100 ms, CI's `clone --filter=blob:none --depth=1 --sparse --single-branch`
in seconds, a developer's `git fetch` in the time it takes to read the output, fresh clones as static
bundles (weekly full + daily/hourly chain) so bytes move bucket → laptop and never through a server.
**Fast clone + fast catch-up through bundles is the north star** (`docs/BUNDLE_URI_DESIGN.md`).
in seconds, a developer's `git fetch` in the time it takes to read the output, fresh clones and stale fetches using negotiated reusable packs so bulk bytes can move directly to clients.
**Fast clone and catch-up through proved static packs is the north star**
([design and current scope](docs/PACKFILE_URI_DESIGN.md)). Native anonymous-read delivery is implemented;
protected-client qualification and scale acceptance remain to be established and measured.
4. **All the features a git host needs, and only those**: smart HTTP v0/v2 (ls-refs, fetch with
filter/shallow/deepen, receive-pack atomic/delete/tags/push-options/report-status-v2), bundle-uri, LFS,
filter/shallow/deepen, receive-pack atomic/delete/tags/push-options/report-status-v2), negotiated packfile delivery, LFS,
`<owner>/<repo>` namespaces, per-repo push policy and settings, ref events, a browsing web UI + one JSON API +
one SDK (`repos.js`), tasks/narration so nothing ever waits silently. Not in scope: code review, merge
queues, CI, issues — those live elsewhere and build on this.
5. **Works great for developers and their laptops.** One auth story (browser sign-in through your identity
provider, a token for git), one install script, `git` does the rest; errors tell you the fix; every long
wait is narrated. The developer on a rebased branch must get *cheaper*, never slower.
6. **Predictable for the systems that build on it**: stable, immutable, cacheable, CDN-able artefacts
(bundles, packs, sha-addressed API answers); O(1) ref lookups; latency that does not depend on which
(packs, sha-addressed API answers); O(1) ref lookups; latency that does not depend on which
instance you hit or how many refs exist; a provenance log you can rewind (`walgit wal materialize --at-seq`).
7. **Use the tools; don't reinvent them.** Upstream `git` where it is right (repack, bitmaps, bundle create,
7. **Use the tools; don't reinvent them.** Upstream `git` where it is right (repack, bitmaps,
upload-pack), `gix` where it is faster and measured, Rust + tokio + axum for the server, the object store
as it is (range reads, compose / multipart copy, CAS), a plain nginx or CDN in front of static bytes,
content addressing everywhere, the WAL's ergonomics (`walgit wal ls|show|materialize`) as a first-class
Expand All @@ -50,8 +51,8 @@ anyone can run against a bucket, and predictable enough that tooling can build o
|---|---|
| Cold instance is useful in seconds | `ls-remote` of the largest repository < 1 s on a fresh instance, even while it installs that repository's packs |
| CI clone of the monorepo | `clone --filter=blob:none --depth=1 --sparse --single-branch` in seconds, not minutes (reference: 2075 s → 8 s on a 57 GiB / 73 M-object repository) |
| Developer catch-up | a days-stale `fetch` on main = exactly the bundle slots missed + < 1 h of objects from upload-pack |
| Fresh clone of the monorepo | bytes through the server ≈ one hour of pushes; the rest is static bundles (reference: 32.7 GB static, 2.8 MB through upload-pack) |
| Developer catch-up (target) | a stale `fetch` negotiates useful proven packs plus its uncovered requested graph; small fetches stay dynamic |
| Fresh clone of the monorepo (target) | reusable packs carry the proven baseline; validate URI packs + dynamic remainder against ordinary Git and measure both server and client cost |
| Web UI on the monorepo | tree/blob/commits without packs on disk, ~100–200 ms warm |
| Push | acknowledged only after the bucket ACKs; one CAS per batch; the host that maintains a repository writes it |
| Consistency | push then fetch anywhere sees it; concurrent pushers: exactly one winner (the simulation suite) |
Expand All @@ -61,5 +62,5 @@ anyone can run against a bucket, and predictable enough that tooling can build o
## What we deliberately do **not** optimise for

- Millions of tiny repositories (the long tail is served, not tuned for).
- Running a 30 GB base repack on a tmpfs host (that is a job for the host with the SSD, weekly).
- Running a 30 GB base repack on a tmpfs host (that is a job for the host with sufficient disk).
- Forking git or inventing an object format: weird stuff happens *around* git, never inside it.
Loading
Loading