Part of #72.
KAS_WORK_DIR=work/<name>/ plus KAS_REPO_REF_DIR=work/.repo-ref, _mackas_derive_project()'s third cwd case, and a confirm()-offered move for checkouts converted by --from before this landed.
Gated on virtiofs verification — verified 2026-08-24: proceed
The gate is cleared. Verdict: works, with two caveats to build in. High confidence. Ship the shared ref
dir; do not fall back to full per-project clones on filesystem grounds.
Method: 47 assertions run twice from inside the container via mackas exec — once with the object store on
virtiofs (the work/ bind mount) and once on ext4 (a volume) as a control. Every assertion matched
line-for-line; only loose-object rounding differed. Coverage included what virtiofs classically breaks —
hardlinks (st_nlink and inode identity), rename() over an existing file, flock, fcntl record locks,
mmap, fsync — plus the whole alternates path: file created and resolved, objects genuinely not duplicated
(4 KiB borrower against a 20 MB reference), fsck clean, all reachable objects readable, an object only the
reference holds readable from the borrower, gc in the borrower neither absorbing borrowed objects nor
dropping the alternates file, --dissociate, and git's hardlinking local-clone path.
The assertions were themselves mutation-controlled: with --reference omitted the borrower duplicated all
10 MB, and with the reference moved aside cat-file and fsck both failed, then recovered when it returned.
So they can fail.
Caveat 1 — alternates must be rewritten to a RELATIVE path
kas writes the absolute, container-namespaced path into .git/objects/info/alternates, which makes the
checkout unreadable from macOS: host-side git log / status / fsck fail with unable to normalize alternate object path (rc 128/26/128). That is not academic — skills/mackas/SKILL.md tells users to run
host-side git -C work/<layer> to confirm their commit stack survived a --skip build, and #72 calls
hand-typed work the primary workflow.
A path relative to .git/objects resolves correctly from both namespaces (verified). That imposes a
structural requirement: the reference store must sit at a fixed relative offset from the clones, i.e.
inside the work tree at work/.repo-ref — not at a separate /repo-ref mount. The layout this issue
already specifies is therefore correct, and now has a reason attached; treat it as load-bearing rather than
incidental, and do not let a later cleanup relocate it.
Caveat 2 — never gc/repack --prune the reference while a build may read it
Pruned objects vanish from under a borrower. The concurrency case passed on both filesystems, so this is a
git-level hazard rather than a virtiofs one — which means it will not announce itself.
What this did NOT establish
- kas's own plumbing is untested. The experiment tested git's semantics deliberately, not
KAS_REPO_REF_DIR through kas or kas-container's /repo-ref forwarding — exercising kas's repo handling
against real checkouts is what the safety rules forbid. A kas-level smoke test in a throwaway workspace
still has to happen before this milestone closes.
- Scale. Synthetic repos: 10-12 commits, 20 MB of incompressible blobs, one branch, no submodules. poky is
~500k commits with very different pack characteristics. No size-dependent behaviour was observed, but
clone/fetch wall-clock at poky scale is unmeasured.
- Cross-namespace concurrency. Four parallel clones inside one container VM passed. A host-side macOS git
process and a container-side git process writing the same reference simultaneously was not tested — the
one-VM rule does not cover it, and virtiofs cache coherency between namespaces is where a surprise is most
likely.
- The saving is real but partial: a borrower still fetches whatever the reference lacks, so the ref dir needs
its own refresh step to stay useful. Worth a line in the docs.
Highest risk in the epic; do not bundle it with anything.
Note the ordering wart: M3-M5 give pinned projects distinct volumes and configs while work/ is still flat, which is precisely the configuration where the layer-reset hazard bites hardest (separate TMPDIRs mean nothing forces the rebuild that would surface the mismatch). M6 should not lag far behind M3.
Size: L. Risk: highest in the epic.
Part of #72.
KAS_WORK_DIR=work/<name>/plusKAS_REPO_REF_DIR=work/.repo-ref,_mackas_derive_project()'s third cwd case, and aconfirm()-offered move for checkouts converted by--frombefore this landed.Gated on virtiofs verification— verified 2026-08-24: proceedThe gate is cleared. Verdict: works, with two caveats to build in. High confidence. Ship the shared ref
dir; do not fall back to full per-project clones on filesystem grounds.
Method: 47 assertions run twice from inside the container via
mackas exec— once with the object store onvirtiofs (the
work/bind mount) and once on ext4 (a volume) as a control. Every assertion matchedline-for-line; only loose-object rounding differed. Coverage included what virtiofs classically breaks —
hardlinks (
st_nlinkand inode identity),rename()over an existing file,flock,fcntlrecord locks,mmap,fsync— plus the whole alternates path: file created and resolved, objects genuinely not duplicated(4 KiB borrower against a 20 MB reference),
fsckclean, all reachable objects readable, an object only thereference holds readable from the borrower,
gcin the borrower neither absorbing borrowed objects nordropping the alternates file,
--dissociate, and git's hardlinking local-clone path.The assertions were themselves mutation-controlled: with
--referenceomitted the borrower duplicated all10 MB, and with the reference moved aside
cat-fileandfsckboth failed, then recovered when it returned.So they can fail.
Caveat 1 — alternates must be rewritten to a RELATIVE path
kas writes the absolute, container-namespaced path into
.git/objects/info/alternates, which makes thecheckout unreadable from macOS: host-side
git log/status/fsckfail withunable to normalize alternate object path(rc 128/26/128). That is not academic —skills/mackas/SKILL.mdtells users to runhost-side
git -C work/<layer>to confirm their commit stack survived a--skipbuild, and #72 callshand-typed work the primary workflow.
A path relative to
.git/objectsresolves correctly from both namespaces (verified). That imposes astructural requirement: the reference store must sit at a fixed relative offset from the clones, i.e.
inside the work tree at
work/.repo-ref— not at a separate/repo-refmount. The layout this issuealready specifies is therefore correct, and now has a reason attached; treat it as load-bearing rather than
incidental, and do not let a later cleanup relocate it.
Caveat 2 — never
gc/repack --prunethe reference while a build may read itPruned objects vanish from under a borrower. The concurrency case passed on both filesystems, so this is a
git-level hazard rather than a virtiofs one — which means it will not announce itself.
What this did NOT establish
KAS_REPO_REF_DIRthrough kas or kas-container's/repo-refforwarding — exercising kas's repo handlingagainst real checkouts is what the safety rules forbid. A kas-level smoke test in a throwaway workspace
still has to happen before this milestone closes.
~500k commits with very different pack characteristics. No size-dependent behaviour was observed, but
clone/fetch wall-clock at poky scale is unmeasured.
process and a container-side git process writing the same reference simultaneously was not tested — the
one-VM rule does not cover it, and virtiofs cache coherency between namespaces is where a surprise is most
likely.
its own refresh step to stay useful. Worth a line in the docs.
Highest risk in the epic; do not bundle it with anything.
Note the ordering wart: M3-M5 give pinned projects distinct volumes and configs while
work/is still flat, which is precisely the configuration where the layer-reset hazard bites hardest (separate TMPDIRs mean nothing forces the rebuild that would surface the mismatch). M6 should not lag far behind M3.Size: L. Risk: highest in the epic.