Architecture
noya-cli ships two binaries, noyafmt and noyavalidate, over one
shared library so the binaries, their manpages, and their shell
completions are generated from a single definition and cannot drift.
Layers
src/lib.rsdefines the command-line surface once: theclapderive structsNoyafmtCliandNoyavalidateCli, and the buildersnoyafmt_commandandnoyavalidate_commandthat return the underlyingclap::Commandtrees. Both binaries parse argv through these; the build script consumes the same trees.src/bin/noyafmt.rsformats YAML through noyalib’s CST formatter withrustfmt-style ergonomics:--checkfor CI gates,--writefor in-place rewrites, stdin to stdout for editors.src/bin/noyavalidate.rsvalidates syntax, renders errors withmiette, validates each document against a JSON Schema 2020-12 contract when--schemais given (the schema may be YAML or JSON), and with--fixrewrites the input through the CST formatter, normalising whitespace and quoting without changing meaning. The README documents the exit codes.build.rsgenerates the manpages (clap_mangen) and the bash, fish, zsh, and PowerShell completions (clap_complete) intoOUT_DIRat build time.make assetscopies them intodocs/andcomplete/so the committed copies never lag--help; the version gate checks the manpages carry the crate version.
Install contract
GNUmakefile implements the Unix contract: make, make test,
make install and make uninstall honouring PREFIX (default
/usr/local) and DESTDIR, installing binaries, manpages, and
completions to FHS paths. CI stages an install into a temporary
DESTDIR on every push. pkg/ carries the Homebrew formula, Scoop
manifest, AUR PKGBUILD, and flake.nix, all generated from the
release build; the channel manifests roll after each release’s
artefacts exist because they embed checksums.
Testing
Integration tests run the binaries as processes. Two libFuzzer targets
feed arbitrary argv through the clap trees (fuzz_argv) and the
derive structs (fuzz_derive_parse); CI replays the seed corpus on
every push.
Lockstep
The crate pins noyalib at the identical =0.0.X and releases with
it (core ADR-0005).