fix(project): pick newer cargo target binary by mtime#51
Merged
Conversation
…inary The discover_rust_binaries() preference for target/release over target/debug masks behavioral check failures when target/release lingers stale from past builds. Surfaced during v0.4.0 spec sync work — the new p2-must-schema-print check kept reporting Fail despite the schema subcommand being visible in target/debug/anc --help; the runner was probing a stale target/release/anc that predated the subcommand. Adds rule 3 to the Dogfooding Safety section (current behavior + workaround: cargo build --release before dogfooding, or trash target/release). Adds a corresponding rule under 'Rules for new behavioral checks' so future checks that exercise help-surface get the right pre-flight. Cites docs/solutions/test-failures/stale-release-binary-dogfood-fail-2026-05-07.md for the full investigation, root cause, and fix-candidate analysis. Pairs with the next commit on this branch which lands the mtime-based binary-discovery fix and updates this rule to reflect the new behavior.
discover_rust_binaries() previously preferred target/release/<bin> unconditionally when both directories existed. In dev workflows where cargo run / cargo test only refresh debug, target/release lingers stale from past builds and behavioral checks probed yesterday's --help. The v0.4.0 spec sync surfaced this when the new p2-must-schema-print check kept reporting Fail despite the schema subcommand being visible in target/debug/anc --help — captured help was 1071 bytes vs 1145 from a direct invocation, exactly one subcommand line shorter (the line that lived only in debug). The fix replaces existence-only selection with mtime comparison: when both binaries exist, return the one with the more recent modified time. Ties and metadata-failures fall back to debug (cargo's dev-flow default). CI scenarios where only one profile is built are unchanged — fall through cleanly to the existence check. Adds two unix-gated tests: - test_discover_picks_newer_artifact_by_mtime: stamps target/release/myapp one hour in the past while target/debug/myapp stays at 'now'; asserts Project::discover returns the debug path. Regression for the original bug. - test_discover_picks_release_when_newer: symmetric — stamps debug old and asserts release wins. Locks in that the function still does the right thing after a fresh cargo build --release. Updates the CLAUDE.md Dogfooding Safety rule (added in the previous commit on this branch) to describe the new mtime-based behavior. The 'Rules for new behavioral checks' subsection gains a NEVER directive against reverting to the always-prefer-release shape. Backstory: docs/solutions/test-failures/stale-release-binary-dogfood-fail-2026-05-07.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces
discover_rust_binaries()'s always-prefer-release heuristic with mtime-newest-wins so dev workflows wherecargo run/cargo testonly refresh debug stop probing staletarget/release/<bin>binaries. The v0.4.0 spec sync surfaced the trap onp2-must-schema-printagainst anc itself.Changelog
Changed
src/project.rs::discover_rust_binariesnow picks the newer oftarget/release/<bin>andtarget/debug/<bin>by mtime when both exist. Ties and metadata failures fall back to debug (matches cargo's dev-flow default). CI scenarios where only one profile is built are unchanged.Documentation
CLAUDE.mddescribing the mtime-based selection, with aNEVERdirective against reverting to the always-prefer-release shape.Type of Change
feat: New feature (non-breaking change which adds functionality)fix: Bug fix (non-breaking change which fixes an issue)refactor: Code refactoring (no functional changes)perf: Performance improvementdocs: Documentation updatetest: Adding or updating testschore: Maintenance tasks (dependencies, config, etc.)ci: CI/CD configuration changesstyle: Code style/formatting changesbuild: Build system changesBREAKING CHANGE: Breaking API change (requires major version bump)Related Issues/Stories
target/release/ancmaskingp2-must-schema-printregressions during v0.4.0 spec syncdocs/solutions/test-failures/stale-release-binary-dogfood-fail-2026-05-07.mdPENDING_FAILSallowlist forp2-schema-printwas added intests/dogfood.rs)Files Modified
Modified:
src/project.rs:discover_rust_binariesswitches from existence-only release-over-debug preference to mtime-based selection via a newpick_newer_artifacthelper. Adds two unix-gated tests (test_discover_picks_newer_artifact_by_mtime,test_discover_picks_release_when_newer).CLAUDE.md: Dogfooding Safety section gains rule 3 describing the new behavior; theRules for new behavioral checkssubsection gains aNEVERdirective locking the new shape in.Created:
Renamed:
Deleted:
Testing
anc check .against this branch;p2-schema-printno longer needs a manualcargo build --releaseto flip from Fail to Pass)Test Summary:
cargo testreports 588 passed, 2 ignored across 7 suites. The two new unit tests usetempfile-style temp dirs andFile::set_modified(stable since 1.75) to construct binaries with controlled mtimes; gated to#[cfg(unix)]because mtime semantics under Windows file-attribute caching are not the semantics this regression asserts against. Pre-push gate (fmt, clippy-Dwarnings, test, cargo-deny, Windows compat) passed before the push.