Contributing
Development
Toolchain, everyday commands, working rules and the CI gates.
Toolchain
- Stable Rust 1.95 or newer. This is
rust-versionin the rootCargo.toml, the floor egui 0.36 needs. CI uses stable. - There is no WASM target and no
craft-*dependency. - The only embedded font is Poppins, plus the default fonts that ship inside egui.
Everyday commands
cargo build -p postguy # desktop app
cargo run -p postguy -- --workspace DIR --control /tmp/postguy-control.json
# opt-in control channel (loopback, fresh owner-only token)
cargo run -p postguy-cli -- run --script STEPS.json --root DIR # engine harness
cargo run -p postguy-cli -- ui --control FILE inspect # or command/set/screenshot
cargo xtask ci # fmt, clippy -D warnings, test, layers, assets, parity, deny
cargo xtask layers # dependency layering only
cargo xtask assets [--write] # asset policy against ATTRIBUTION.toml (ATTRIBUTION.md regenerate)
cargo xtask parity [--partial|--json] # parity checklist validation and progress
cargo xtask deny # licences/sources (delegates to cargo-deny when installed)
cargo xtask size [--skip-build] # release binary sizes against the size budgets
cargo xtask bench [--check] [--debug] # headless frame-time capture (10k tree, 10 MB Raw)
cargo xtask icons [--check] # regenerate ui-egui/src/icons_gen.rs from assets/icons
cargo xtask logo [--check] # rasterize assets/logo/postguy.svg into PNG sizes
cargo xtask fuzz --time 300 [--seed N] # mutation fuzzing (registered targets)
cargo xtask screenshots [--out DIR] # render review screenshots into target/screenshots/
Import a file and generate a snippet
Each postguy-cli call process starts with no workspace open. It fails with no workspace is open; call workspace_open first.
To import a file and generate a snippet, run the steps as one script. Tool arguments take ids, so use a collection id and request id you read from collection_list.
cargo run -p postguy-cli -- run --script steps.json --root DIR
[
{"tool": "workspace_open", "args": {"path": "ws"}},
{"tool": "import_file", "args": {"path": "collection.json"}},
{"tool": "collection_list", "args": {}}
]
Then add a snippet_generate step with the ids from that output. See Automation tools for the argument list.
Working rules (short form; AGENTS.md is the law)
- Use conventional commits (
feat(http): follow redirects with cookie capture) and branch as<type>/<slug>. Commit only green states.mainis the integration branch. - Scope builds and tests to the crates you touched (
-p,-j 2, under a timeout). The full sweep is CI's job (cargo xtask ci), and CI runs it on every PR. - Build every feature in this order: engine API, then automation tool (with an end-to-end test), then UI. A feature without its tool is not done. See the automation README and Adding a feature.
- Keep tests hermetic. Loopback servers live in
postguy-testkit. Tests never touch the internet. Fuzz findings become synthetic regression tests that you see failing first. - Update the parity row of the feature you touched.
- Verify UI changes in one of these ways:
- Run
cargo run -p postguy-ui-egui --example shot -- OUT.png dark. - Run
cargo xtask screenshots. - Launch the app with
--controland usepostguy-cli ui.
click,keyandtypeare not emulated. See Known gaps. - Run
Gates the CI bundle runs
cargo xtask ci runs these in order:
fmt --checkclippy --workspace --all-targets -D warningstest --workspacelayersassetsparitydeny
clippy.toml allows unwrap, expect and panic in tests. It forbids egui's checkbox and radio draw paths in favour of our widgets.
Parallel agents
- Use a separate
CARGO_TARGET_DIRand a separate git worktree for each agent. - Ad-hoc spike crates opt out of the workspace with an empty
[workspace]table in their manifest.