# Contributing to PackFS ## Before changing anything Read [`concept.md`](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`](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`](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 ```sh 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.