Contributing
Thank you for your interest. We welcome contributions of all sizes. A typo fix is as useful as a feature. This document explains how to prepare and submit a change.
File an issue
Section titled “File an issue”- Search open issues before you open a new issue.
- Use the bug report template or the feature request template.
- Do not open a public issue for a security vulnerability. Read
SECURITY.md.
Local setup
Section titled “Local setup”Install these prerequisites before you run the checks:
- Python 3.12 or later, for the Python suites and the documentation generator.
justanduv, which resolve every Python tool for each recipe.- bats-core and ShellCheck, for the Bash suites.
- yamllint, yamlfmt, and markdownlint-cli2, for the format checks.
- Node.js 22 or later with Corepack, for the JavaScript suite and the documentation build.
- Rust and Cargo, for the skill-overlap analyzer tests.
git clone https://github.com/paulnsorensen/easy-cheese.gitcd easy-cheesebrew install just uv bats-core yamllint yamlfmt markdownlint-cli2 node rustcorepack enablejust checkjust check uses uv to resolve the Python tools temporarily. It builds every skill archive before any archive executes.
Build skill archives
Section titled “Build skill archives”Each Python skill ships one executable archive at skills/<skill>/scripts/<skill>.pyz.
Wedge builds self-contained archives at build time. It is not a runtime dependency.
Users run the archive directly with Python; no loader or first-run download exists.
The main branch tracks no archives; Git ignores them.
On every merge to main, the publish dist workflow builds them and appends one commit to dist, the default branch.
That commit holds the full main tree plus the archives, so pull requests never conflict on an archive.
Branch from main and open pull requests against main. A branch cut from dist carries archives and fails CI.
Run just wedge-build after a fresh clone, and after changing runtime source under src/, pyproject.toml, uv.lock, a phase contract, or a wedge.toml.
just wedge-buildjust wedge-build builds each skill through the pinned Wedge and rewrites its archive.
The archive closure comes from uv.lock: the schemas’ dependencies plus the runtime dependency group in pyproject.toml.
requirements/runtime.txt pins the same closure for the test and typing environments; a test keeps the two equal.
To bump fromargs, update the runtime group in pyproject.toml, run uv lock, update requirements/runtime.txt and requirements/typing.txt, then run just wedge-build.
To bump Wedge, change the commit in tools/wedge/pyproject.toml, run uv lock --project tools/wedge, then run just wedge-build.
Each Python skill declares its public subcommands in commands.py.
Declare each handler with the @bundle_command("<name>") decorator at its definition site.
The decorator records the command name on the function. It does not create a mutable registry.
Compile each decorated handler into a command with derive_command(handler, "<summary>").
Collect the results in an immutable COMMANDS tuple.
validate_command_surface rejects a declared name that COMMANDS omits.
It also rejects a COMMANDS entry that no decorator declares.
Make each handler accept list[str].
Build the command surface with fromargs.App and return build_app().run(argv).
A fromargs handler returns data; fromargs prints it as one JSON document on stdout.
Raise fromargs.CliError for a refusal; fromargs writes one JSON line, {"error", "exit_code"}, to stderr.
Write diagnostics to stderr. Return an integer process status.
Do not modify sys.argv. Do not run the target through runpy.
See src/easy_cheese/skills/affinage/commands.py for a complete manifest.
Do not commit a .pyz archive. just test builds the archives before the suites run, and a test fails when main tracks one.
Documentation style
Section titled “Documentation style”Follow the repository guidance for project terms and the established cheese flavor.
For other editorial decisions, follow the Google developer documentation style guide.
Write directly to the reader. Use active voice and sentence case for headings.
Format code names with backticks. Use descriptive link text.
Edit root documents such as README.md and CONTRIBUTING.md. The documentation build generates copies under website/content/docs/.
Run tests
Section titled “Run tests”# Run every suite: skill validators, Python, JavaScript, Bash, and Rust.just test
# Run the full gate: format, lint, types, tests, documentation, and archives.just checkRun just check before you open a pull request.
Submit a pull request
Section titled “Submit a pull request”- Fork the repository and create a topic branch from
main. - Make your change. Keep each commit focused on one concern. This structure helps reviewers.
- Use Conventional Commits for the pull request title.
Examples include
feat: add X,fix: handle Y, anddocs: explain Z. The squash merge uses the pull request title as the commit subject. - Complete the pull request template. Explain why the change is necessary.
- Wait for CI to pass. Address the review comments.
Merge a pull request
Section titled “Merge a pull request”The Mergify merge queue merges every pull request into main.
Do not use the merge button.
When the pull request is approved and CI is green, comment @mergifyio queue on it.
The queue merges main into the pull request, runs the required checks again, and squash-merges it.
The queue merges one pull request at a time, so main receives only trees that CI tested.
To remove a pull request from the queue, comment @mergifyio dequeue.
The queue rules are in .mergify.yml.
Code of Conduct
Section titled “Code of Conduct”The Contributor Covenant governs participation in this project. You agree to follow it when you contribute.
License
Section titled “License”Your contribution uses the same license terms as the project. Read LICENSE.