Contributing to aslice

aslice keeps deprecated Intel Macs (macOS 10.11–12, x86_64) useful. Contributions land in three places, in rough order of what the project needs most:

  1. The orchards — packages. New formulae, version bumps, patches that keep old software building on old OS releases, better tests.star smoke tests. This is the daily work and the easiest way in.
  2. The farm — build time. Spare Intel Macs can enroll as community evidence builders (aslice farm enroll + --reproduce-only): your machine rebuilds published jobs and reports digest agreement. Your machine runs the same code as the official farm, but its results carry no publication authority (BUILD-INFRA §7.4).
  3. aslice itself — the manager is C++20. Talk in an issue before writing large features; the design docs (docs/DESIGN.md and companions) are the spec, and PRs that contradict them need to win the argument first.

Project terms, acronyms, and the Homebrew translation table: docs/NOMENCLATURE.md.

Ground rules (read these before your first PR)

Writing a formula

Target changes at develop (dev). Staging uses beta and production uses master, all in the same repository and its mirrors. This applies to aslice and third-party orchards as well as core and extended. Build and freeze a candidate once, then promote its identical artifacts through staging to prod. Do not hardcode environment-specific configuration or edit payloads to change version suffixes. See ORCHARD-POLICY §18.1 for branching and ORCHARD-POLICY §18.2 for x.y.z-develop → x.y.z-beta → x.y.z, required bumps, and promotion-failure reports.

Read PACKAGE-FORMAT §3 and PACKAGE-FORMAT §6 for the format, then docs/ORCHARD-POLICY.md for the acceptance rules. Reviewers check the following:

The local loop

aslice create <url>                     # scaffold a formula from a tarball
aslice lint ./my-formula                # schema + policy + --new-package rules
aslice build ./my-formula               # full sandboxed pipeline, the same one CI runs
aslice build ./my-formula --keep --shell  # drop into the sandbox at the failed phase
aslice test my-formula                  # tests.star against the installed result

Local and farm builds use the same pipeline, but host capability and OS coverage still differ. orchard ci reports tests deferred to the farm; a local pass alone does not prove the complete matrix.

Porting from Homebrew

The Ruby-formula importer is planned for tools/ (DESIGN §13.3). It will handle the mechanical translation; you handle the judgment calls:

Homebrew aslice
keg_only link = false + link_reason (PACKAGE-FORMAT §3.8)
caveats notes — actionable only
post_install does not translate — declare [service], use notes, or rethink; a vendor installer script the payload cannot replace is declared as a graft (PACKAGE-FORMAT §3.11)
uses_from_macos rejected, except allowlisted frameworks
deprecate!/disable! [deprecation] table (PACKAGE-FORMAT §3.14)
livecheck block [livecheck] table (PACKAGE-FORMAT §3.15) — usually near-mechanical
plist_options / service [service] table (generated plist)

MacPorts and pkgsrc patches for 10.11-era portability are fair game — credit them in the patch header.

The review process

Merge gates are mechanical (ORCHARD-POLICY §10): lint → sandboxed build on every declared flavor → smoke-run on every OS in [min_os, 12] → ABI gate for provider bumps → graft rehearsal for graft-bearing binaries, with dependent rebuilds published in the same atomic snapshot. Malware checks and required independent rebuilds remain publication gates; missing capacity leaves releases pending. During single-owner launch, the owner's merge is the final human release approval. The publisher automatically delivers an authenticated candidate to the dedicated networked release Pi, verifies returned signatures, and activates the complete release atomically (KEY-RUNBOOK §2.1). Clients discover it at metadata refresh; publication does not install it.

Owner approval applies to all changes during single-owner launch, including new core packages, versioned lineages, abi = true variants, system-software and system-patch packages, and policy changes. The owner may approve their own changes; second-reviewer and maintainer-vote requirements are superseded for this phase (ORCHARD-POLICY §17). Independent maintainers can help review; multi-party governance remains a future transition. Automated gates cannot be waived.

C++ changes

To check a change locally, configure a Debug build, build it, and run the same format and analysis targets used by CI:

cmake -S . -B build/check -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build/check
cmake --build build/check --target format-check tidy
ctest --test-dir build/check --output-on-failure

Use cmake --build build/check --target format when you want to rewrite formatting. The checking targets never rewrite files. Docker supplies the LLVM 22 compiler, formatter, and analyzer baseline; docker build -t aslice-check . runs the gates. For ASan and UBSan, add --build-arg ASLICE_SANITIZERS=ON. That matrix uses libstdc++ because the Ubuntu libc++abi exception-message path triggers an allocation/deallocation mismatch under ASan. The ordinary matrix retains libc++ coverage; sanitizer diagnostics remain enabled. Native Windows builds run the portable suites and analyze their own compilation database, including the Windows filesystem implementation. POSIX lifecycle tests run on Linux.

CMake exports compile_commands.json. Set ASLICE_CLANG_FORMAT and ASLICE_CLANG_TIDY to tool paths at configure time if they are not on PATH. CLion reads the checked-in configurations; validate its bundled analyzer with clang-tidy --verify-config. For a standalone analyzer, install its matching resource headers as well as the executable. tools/quality.py tidy discovers MinGW's C++ and CRT include paths from the compilation-database compiler. --resource-dir or ASLICE_CLANG_RESOURCE_DIR can select matching Clang headers. Do not combine different LLVM versions' intrinsic headers.

Write C++20 with the LLVM layout, four-space indentation, attached braces, and a 100-column limit. Use braces for every control body, with the body on separate lines. Types use PascalCase; functions and variables use snake_case; private members end in _. Include the headers that declare what you use, declare one variable per statement, and name individual imports instead of using a namespace directive. Document how long borrowed views remain valid.

Validated objects come from factories and keep their invariants private. Pass typed candidates, dependencies, targets, inventories, and generations between subsystems. Parse and serialize JSON at boundaries. The unsigned fixture adapter owns inline payloads and generation JSON; core package and resolver targets must not depend on it. A manifest's document and digest cannot be changed independently.

Fallible operations return core::Result<T>, backed by pinned tl-expected 1.3.1. Translate library exceptions within the owning boundary. Internal validation unwinding is caught there; the CLI renders diagnostics and maps failure codes to exit statuses. Own descriptors, native handles, SQLite statements, and crypto contexts with move-only RAII, including error paths.

Enabled clang-tidy diagnostics are errors. Generated code and dependencies are excluded. Any suppression must name its check and explain the specific C API or platform constraint beside the affected operation; blanket file suppressions and accepted-warning baselines are not permitted. Formatting, Linux analysis, native Windows builds/tests and analysis, sanitizer tests, demonstrations, and documentation checks are merge gates.

Documentation style

Follow STRUCTURE.md for file placement and the boundary between durable documentation and work records.

The docs ship with the manager, and reviewers hold them to the same bar as formulae. Write the way the code is written: mechanics first, one fact per sentence, one idea per paragraph.

Documents with revision records end with one unnumbered ## History section. Put a Markdown table inside one closed <details> disclosure, with <summary>Document revision history</summary> and no open attribute. Leave a blank line before and after the table. Use Version | Date | Changes for versioned documents and Date | Changes for unversioned documents; do not introduce versions for an unversioned document.

Keep one row per historical entry. Remove exact duplicates, but retain distinct accounts of the same revision as separate rows. Sort explicit document versions numerically, newest first; place a recorded version range by its newest endpoint. Put entries without a version after versioned entries. Where chronology cannot be established, preserve source order. Keep the recorded date precision and use Not recorded for missing metadata rather than inferring it from adjacent entries or the current status date. Escape table pipes, including pipes in inline code.

Keep current status, version, date, and substantive qualifications at the top; move revision notes from headers and scattered footers into History. Preserve numbered sections and existing link targets. Increment an existing document revision and record each documentation change; for an existing unversioned history, add a dated entry. Software release versions are separate. Documents without revision records need no History section. Archived sources, provenance records, and narrative discussions of history are outside this convention.

Documentation checks

Install the dependencies and run the offline checks from the repository root:

python -m pip install -r tests/requirements.txt
python tests/check_docs.py
python -m unittest discover -s tests -p test_docs.py
python tests/check_contracts.py
python -m unittest discover -s tests -p test_database.py
python -m unittest discover -s tests -p test_recovery_contract.py
python .agents/skills/ref-curator/scripts/refs.py verify --root .
git diff --check

check_docs.py --json emits machine-readable findings. Errors fail the gate; style warnings remain visible. The checker validates local paths with exact case, heading fragments, explicit anchors, citation labels, reference-style links, fences, and table structure. It supports CommonMark, GFM tables, and Pandoc-style definition lists. External URL availability and factual correctness require separate review.

History sections and REPOSITORIES' section 9 historical amendment record retain their citations; their links remain checked. Code and inline literals are not prose. Archive originals beginning at the Full captured source heading retain upstream syntax; wrappers remain checked, with bare source-section locators referring to the captured edition. New checker exceptions need a documented reason and a focused regression case.

Before accepting structural changes, inspect rendered glossary, dense-table, long-specification, and man-page examples. Check wrapping, heading destinations, literal placeholders, and definition lists, using Pandoc man output where applicable. Compare histories, requirements, and code examples against the pre-edit files. Archive changes also require byte-for-byte preservation checks of original captures and notices before regenerating checksums.

Conduct

There is no code of conduct document, and there won't be one. People are expected to be decent to each other without a policy forcing it.

Discussion here is direct. This is not a corporate project, and nobody is going to wrap technical feedback in three layers of diplomacy: if you are acting like an idiot, expect to be told that you are acting like an idiot. That is not a conduct violation — it is how direct technical projects talk. Dish it out in good faith, take it in good faith, and keep it about the work.

Maintainer judgment on what's over the line is final. The line is short and obvious: keep it about the work.

License

Original contributions are licensed under Apache-2.0, the project's license. Third-party material retains its applicable license and attribution. By submitting a contribution you agree to Apache-2.0's contribution terms.


History

Document revision history | Date | Changes | |---|---| | 2026-09-27 | Establish typed C++ boundaries, command registry help, and mandatory formatting, analysis, and sanitizer checks; retain fixture wire identities. | | September 2026 | Add executable SQLite schema and recovery-model checks; these do not establish runtime or platform acceptance. | | September 2026 | Move documentation checker instructions here and remove standalone audit, coverage, checks, and remediation reports from the project documentation. | | September 2026 | Consolidate revision notes into a collapsible history table and document the history convention; historical wording is unchanged. | | September 2026 | grafts: the zero-install-time-code ground rule gains its declared exception (owner decision) — vendor installer scripts as declared, user-approved, farm-rehearsed grafts (DESIGN §12.15); the rule bullet updated, the merge-gate summary gains the rehearsal gate, and the porting table's `post_install` row gains the graft path. | | September 2026 | editorial pass: prose revised for directness; `min_os` honesty renamed `min_os` accuracy for consistency with AUTHORING.md; documentation style section added. No rule changes. | | September 2026 | prose rewrite throughout: reworded in the project's technical-writing voice; no rule changes. | | September 2026 | NOMENCLATURE.md vocabulary pointer added; no rule changes. | | September 2026 | variant discipline rule updated: the six-variant cap is retired (ORCHARD-POLICY v1.5); variants are governed by need and honest ABI tags. | | September 2026 | prose rewrite of the contribution and review introductions; no rule changes. | | September 2026 | Documentation audit repairs: contract summaries aligned; owner-approved namespace, rollback, GC, naming, prefix, and graft decisions applied where relevant; semantic anchors and explicit citations added. Runtime implementation and platform acceptance remain pending. | | September 2026 | Link the repository structure policy and describe the Homebrew importer as planned; retain writing conventions and checker instructions here. |

Source document