Search/Change a Rust Library-and-CLI Workspace and Check It Against a Reference Tool

Change a Rust Library-and-CLI Workspace and Check It Against a Reference Tool

For AI changes to a Rust workspace of libraries and CLI tools. It starts with a failing test, compares results with the reference tool, avoids unwrap(), and tests every feature combination.

To use this AI rule
## Put Changes in the Owning Crate and Keep Low-Level APIs Lean Treat the repository as a multi-crate workspace that serves both library and command-line users. Read the workspace manifests before editing to learn the minimum supported Rust version, feature graph, crate responsibilities, and public entry points. Separate low-level plumbing from high-level porcelain: - plumbing APIs should favor references, expose mutable working state explicitly, and avoid convenience clones; - porcelain APIs may trade some allocation or ownership for ease of use; - lightweight platform objects should usually borrow the repository; - expensive caches may own or clone repository state when lifetimes would otherwise dominate the API. Use `Options` for branching behavior that can have defaults. Use `Context` for data required to perform the operation and therefore not safely defaultable. Place changes in the crate that owns the relevant data structure or operation. Keep shared command-line behavior in a shared CLI layer rather than duplicating it across binaries. Before changing a public surface, consider both direct library callers and command-line behavior. ## Start with a Failing Test and Compare with the Reference Tool Start behavior changes with a regression test that fails for the intended reason. Keep the test focused on observable behavior; let the Rust compiler cover routine type and ownership mistakes. When implementing an established protocol or file format, use the dominant reference implementation as an oracle where feasible. Run equivalent cases against both implementations and investigate any semantic difference rather than assuming compatibility. Run the existing tests before editing so pre-existing failures are not attributed to the change. Use: - unit tests for local algorithms and data transformations; - integration tests for crate boundaries; - journey tests for end-to-end command-line behavior; - real repositories or realistic datasets for compatibility-sensitive paths. Every assertion message should explain the invariant being checked, not merely state that an assertion failed. Add clear fixture documentation describing the behavior under test and which details are essential. Prefer documentation strings when the fixture system supports them. ## Replace unwrap() with Errors That Say What Failed and Where Never use `unwrap()` in production code. Avoid it in tests as well; prefer `?`, or use `expect()` only with a concise explanation of why the condition must hold. Preserve complete error chains so users can understand what failed and where. Command-line binaries may use a flexible top-level error type, but lower-level crates should follow the workspace's structured error convention. Before adding an error, inspect the crate manifest and nearby code: - if the crate already uses the newer context-carrying error framework, continue that pattern; - if it still uses a legacy derive-based error enum, remain consistent within that crate unless migration is explicitly in scope. In the context-carrying pattern: - create static or formatted messages through the project helper; - add context when propagating a callee error; - raise a standalone message when no callee error exists; - erase typed errors only when a callback boundary requires it; - convert a project exception wrapper into a standard error only at interoperability boundaries. If the project exception wrapper deliberately does not implement the standard error trait, do not force it into generic error APIs. Convert it with the provided boundary method. Tests returning boxed standard errors must map the wrapper before using `?`. Use the established error extension traits and imports instead of rebuilding error chains manually. ## Avoid Extra Clones and Treat Repository Paths as Bytes Prefer references in low-level crates to avoid expensive clones. Do not detach a repository-backed handle unless an owned value is explicitly required and the API cannot accept the attached form. Use the workspace's concurrency abstraction for interior mutability. Do not substitute unrelated synchronization primitives without checking feature compatibility and platform behavior. Treat version-control paths as byte-oriented data, including on platforms whose native path APIs use different encodings. Convert repository paths to operating-system paths only through the project's path utilities or a dedicated boundary type. Do not assume that a valid repository path is valid Unicode. Avoid lossy conversion in parsing, comparison, storage, and protocol code. Measure hot paths before adding ownership, caching, or allocation. Convenience belongs in the high-level layer; low-level primitives should preserve control and predictable cost. ## Test Every Feature Combination, Not Just the Default Build Use the repository task runner for the comprehensive test command, workspace configuration checks, linting, journey tests, and documentation builds. Use direct `cargo test` only when a unit-test-only run is intentionally sufficient. Verify supported release variants, including the default build and any lean or minimal dependency sets. A change is incomplete if it works only with default features. Exercise the workspace's documented feature combinations, including small, lean, maximal, and pure variants where they exist. Check that optional dependencies and platform abstractions compile in each affected combination. On platforms where generated fixture contents vary, use the repository's archive-stabilization mechanism. Prefer packaged fixture archives over platform-local generation when byte-for-byte stability matters. If the repository defines a platform-specific environment flag for archive tests on macOS or Windows, apply it exactly as documented. Do not silently skip the affected tests on other platforms. Run end-to-end command tests for user-visible CLI changes and compare with the reference implementation when practical. ## Write Commits That Feed the Changelog and Mark Breaking Changes Use purposeful conventional commits: - add a conventional prefix only when the change belongs in the changelog; - use `feat:` and `fix:` for user-visible features and corrections; - omit a prefix for internal refactors and chores; - mark every breaking change with a `!` suffix. Write commit subjects that name the user-visible purpose and include the issue or review reference when the project expects one. When a breaking change affects multiple crates, split it by crate if one commit message cannot describe every impact accurately. Put the breaking API change in the first commit and downstream adaptations in a following commit. Treat commit messages as release inputs when release automation derives versioning or changelogs from them. Update high-level guides, contribution instructions, development notes, crate-status records, and stability documentation whenever the code change directly affects them. Use the reference-tool version available in the primary CI environment as the compatibility baseline unless the project defines a stricter target. ## Run the Final Checklist, from Crate Layer to Commit Messages Before completion: 1. identify whether the change belongs to plumbing or porcelain; 2. inspect established patterns in similar crates; 3. confirm error handling matches that crate's current framework; 4. verify no production `unwrap()` was introduced; 5. check all affected feature combinations and release variants; 6. consider library callers and command-line users separately; 7. run focused, workspace, journey, and compatibility tests as applicable; 8. confirm byte-oriented paths remain lossless across platforms; 9. review new clones, detachment, caching, and synchronization for measurable need; 10. update directly related documentation; 11. confirm commit messages describe changelog and breaking-change impact correctly. Report any untested feature set, platform, reference comparison, or release variant with the exact missing prerequisite. Do not claim workspace-wide compatibility from a default-feature unit-test run.