Codify what the history already does so agents and new contributors do not have to reverse-engineer it: the fmt/clippy gates mirroring CI's -Dwarnings, the <scope>: <summary> commit format with the per-module scope table, and the library-side invariants (missing_docs, report ports, data/*.yml embeds, README parity for user-facing changes).
4.5 KiB
AGENTS.md
Conventions for working in this tree. They apply to every commit; the whole history follows them.
Before every commit
Run, in order, and make sure they are clean before committing:
cargo fmt --all
cargo clippy --all-targets --all-features # zero warnings
CI builds and lints with RUSTFLAGS: -Dwarnings, so a cargo build
warning fails the gate too. cargo fmt may amend files you did not
touch — include those changes in the commit (or in a separate fmt:
commit) rather than leaving the tree dirty.
The test suite is heavy (chroots, ssh, network): always run the
#[cfg(test)] modules of what you touch, and the full suite when
changing shared plumbing (report, logfmt, test_support,
debian/). Tests marked #[ignore] shell out or hit the network and
are for deliberate ad-hoc runs (cargo test -- --ignored), not for the
pre-commit pass. Building needs the gpgme/openssl system packages
(pkg-config libssl-dev libgpg-error-dev libgpgme-dev).
Commit messages
There are no conventional-commit types; the format is a component scope and a summary:
<scope>: <short summary>
Rules:
- The scope is the component touched — the module under
src/(file or directory), named after the user-facing subcommand when that differs:pull— source package download (src/pull.rs)chlog— changelog entry generation (src/changelog.rs)build— source package builds, .dsc (src/build/)deb— binary package builds, .deb (src/deb/)put— PPA/archive upload (src/put/)new— package scaffolding (src/new/)lint— tree linting (src/lint/)prune,package_info— remaining subcommand modulescontext— build contexts: local, ssh, chroot/schroot, unshare (src/context/)debian— Debian format primitives: control, versions, checksums, arch (src/debian/)apt,launchpad,distro_info,quirks— archive/distro integrationreport— BuildView/Prompter ports and the views implementing themui,logfmt— terminal rendering and output classificationdata— thedata/*.ymlembed convention itself; content changes to a data file belong to the commit of the module consuming itcli— the binary, argument wiring (src/main.rs)test— test-only changes (shared plumbing:src/test_support.rs)deps— dependency additions/bumps (manifests, lockfile)fmt,clippy— rustfmt/clippy fixupsci,snap,docs— workflows, snap packaging, README
- Use the submodule path when the change is confined to one
(
apt/keyring,debian/version). - A commit touching several components should be split into one commit
per component when practical; otherwise comma-join the scopes without
spaces (
pull,deb). - Summary: imperative mood, lowercase first letter (proper nouns keep theirs: Ubuntu, SRU, lintian), no trailing period, max ~72 characters.
- Body (expected for anything nontrivial): separated by a blank line,
wrapped at 72 columns; explain why, and the design when the approach
was a choice among alternatives. Reference issues as
#123. - Reverts use git's default
Revert "<original subject>".
Examples
chlog: fall back to the changelog history when no version tag exists
ui: ellipsize fake-terminal pane lines wider than the terminal
lint: add pkh lint, wrapping lintian for parity plus pkh-native checks
chlog: number Ubuntu backports with the per-release SRU scheme
deb: resolve cross pkg-config against the target multiarch
pull,deb: add top-level --pocket option
debian/version: dpkg-compatible version comparison
deps: bump git2 to 0.21
fmt: apply rustfmt
docs: refresh the README roadmap for 1.0
Code
- The crate denies missing docs (
#![deny(missing_docs)]insrc/lib.rs): every public item carries a doc comment, and the module list there is the layout map — keep it in sync when adding a module. - Subcommand business logic lives in the library and reports through the
reportports (BuildView,Prompter) instead of printing;src/main.rsis argument wiring only. Subprocess output classification is pure logic inlogfmt, testable without a pty. - Static reference data (series tables, keyserver URLs, licenses,
forges, templates) lives in
data/*.yml, embedded with theembed_data!macro — not in hardcoded tables. - Comments state constraints the code cannot show; no narration.
- Anything user-facing (subcommands, flags, option defaults) is
reflected in
README.md— including its roadmap checklists — before commit.