Files
packfs/CONTRIBUTING.md
T
retoorandClaude Sonnet 5 72e3c900f2 Add PackFS v0: statically linked in-process VFS implementing concept.md
Implements the core design: a mount table published as an atomically-
swapped snapshot; mem/dir/pack/overlay backends; copy-on-write overlay
with copy-up and whiteout deletion; a checksummed append journal;
compaction with exact-duplicate elimination; single-writer/wait-free-
reader concurrency with a structural/content write split; openat2/
Landlock path containment for dir mounts; and load-time pack integrity
validation. Zero required third-party dependencies.

Sanitizer testing (ASan/UBSan) caught and led to fixing a genuine
heap-use-after-free in the snapshot-reclamation path: the textbook
"load pointer, then increment its refcount" pattern left a gap a
concurrent writer could free through. Closed with a small reclaim_gate
rwlock, documented in internal.h and CLAUDE.md since it's a pattern
every refcounted structure in the codebase now follows.

zip/tar import/export backends, recommended in concept.md Section 11,
will not be built — a permanent project decision recorded in CLAUDE.md
since concept.md itself is frozen and cannot be edited to reflect it.

Includes a runnable demo (examples/demo.c, `make demo`) exercising the
library end to end and proving cross-run persistence through the pack
file, plus open-source scaffolding: MIT license, README, CONTRIBUTING,
and a CI workflow running the test suite under ASan/UBSan/TSan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB
2026-09-14 05:44:08 +00:00

2.9 KiB

Contributing to PackFS

Before changing anything

Read concept.md in full. It is the project's specification, not background reading — every backend, lock, and on-disk field in src/ exists because a section of concept.md requires it, and most functions' comments cite the section they implement rather than re-explaining it. concept.md is frozen (see CLAUDE.md): if you believe the design itself needs to change, that belongs in a new document that amends or supersedes it, not in an edit to concept.md.

Then read CLAUDE.md, which states the load-bearing constraints a change must respect (static linking, the write model, the concurrency model, path containment, pack integrity) and the documentation register this project is written in.

Workflow

make test                              # must pass before any PR
cc ... -fsanitize=address,undefined    # ASan/UBSan: see .github/workflows/ci.yml for exact flags
cc ... -fsanitize=thread               # TSan, for anything touching src/upper.c, src/overlay.c, or src/vfs.c

Any change to the concurrency-sensitive files (upper.c, overlay.c, vfs.c) must be run under ThreadSanitizer, not just the plain test suite — a data race there is exactly the class of bug Section 5 of concept.md exists to prevent, and the plain build will not surface it.

Scope

Changes that add functionality concept.md Section 10 lists as explicitly out of scope for v0 (full POSIX semantics, enforced permissions/symlinks/hard links, cross-process concurrency, content-defined chunking/delta compression) should discuss the tradeoff with a maintainer first — those exclusions were deliberate design decisions, not gaps waiting to be filled.

zip and tar import/export backends will not be accepted, full stop — not discussed, not behind a flag. concept.md Section 11 recommends them, but that recommendation is permanently superseded; see CLAUDE.md, "Project decisions that supersede concept.md." This is a harder line than the v0 exclusions above, which are open to future discussion — this one is not.

Static-linking constraint

concept.md Section 11.1 is a hard constraint: the core must build with zero required third-party libraries and zero dynamic loading. In practice this project has no optional-dependency boundary at all: concept.md described one at the zip/tar backend for miniz/libarchive, but per the decision above, that backend will never exist, so there is no path by which a third-party dependency enters this codebase — a change proposing one, for any backend, will not be accepted.

Style

Match the register already in the file you're editing — precise, constraint-labeled comments citing the concept.md section they implement, no filler. See the "Documentation standard" section of CLAUDE.md for the full rule; it applies to code comments and commit messages, not only to .md files.