From 385a42074771940d1a74000c2046c93e8e3a805e Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Thu, 16 Jul 2026 18:43:23 +0000 Subject: [PATCH 1/2] Reorganize Anneal v1 and v2 gherrit-pr-id: Gaso4is5l3ore5u3xhbeclucymmqjxqz7 --- .dockerignore | 2 +- .github/workflows/anneal-release.yml | 74 +- .github/workflows/anneal.yml | 80 +- .vscode/settings.json | 2 +- anneal/Cargo.lock | 1396 ++++++++++++----- anneal/Cargo.toml | 99 +- anneal/LICENSE-APACHE | 1 - anneal/LICENSE-BSD | 1 - anneal/LICENSE-MIT | 1 - anneal/{v2 => }/chase-aeneas-versions.sh | 0 anneal/{v2 => }/check-flake-eval.sh | 2 +- anneal/{v2 => }/flake.lock | 0 anneal/{v2 => }/flake.nix | 0 anneal/{v2 => }/prune-lake-cache.py | 0 anneal/{v2 => }/rewrite-lake-vendor.py | 0 anneal/src/main.rs | 432 +++-- anneal/src/resolve.rs | 276 ++-- anneal/src/scanner.rs | 498 +----- anneal/src/setup.rs | 235 ++- anneal/src/util.rs | 242 ++- .../{v2 => }/tests/test_prune_lake_cache.py | 0 .../tests/test_rewrite_lake_vendor.py | 0 anneal/{ => v1}/.gitattributes | 0 anneal/{ => v1}/.gitignore | 0 anneal/{ => v1}/AGENTS.md | 0 anneal/{v2 => v1}/Cargo.lock | 1394 +++++----------- anneal/v1/Cargo.toml | 112 ++ anneal/{ => v1}/Dockerfile | 10 +- anneal/v1/LICENSE-APACHE | 1 + anneal/v1/LICENSE-BSD | 1 + anneal/v1/LICENSE-MIT | 1 + anneal/{ => v1}/README.md | 0 anneal/{ => v1}/build.rs | 0 anneal/{ => v1}/docker.sh | 6 +- .../docs/agent/01_philosophy_and_pipeline.md | 0 .../docs/agent/02_rust_to_lean_mapping.md | 0 anneal/{ => v1}/docs/agent/03_memory_model.md | 0 .../agent/04_specifications_and_syntax.md | 0 .../docs/agent/05_proof_architecture.md | 0 .../docs/agent/06_tactics_and_tooling.md | 0 anneal/{ => v1}/docs/agent/07_workflow.md | 0 anneal/{ => v1}/docs/design/design.md | 0 anneal/{ => v1}/docs/design/named_bounds.md | 0 anneal/{ => v1}/docs/images/logo.svg | 0 anneal/{ => v1}/examples/abs.rs | 0 anneal/{ => v1}/examples/anatomy.rs | 0 anneal/{ => v1}/examples/checked_add.rs | 0 anneal/{ => v1}/examples/const_generics.rs | 0 anneal/{ => v1}/examples/design_doc.rs | 0 anneal/{ => v1}/examples/linked_list.rs | 0 anneal/{ => v1}/examples/namespaces.rs | 0 anneal/{ => v1}/examples/never_type.rs | 0 anneal/{ => v1}/examples/nopanic.rs | 0 anneal/{ => v1}/examples/positive_usize.rs | 0 anneal/{ => v1}/examples/ptr_concat.rs | 0 anneal/{ => v1}/examples/size_of_align_of.rs | 0 anneal/{ => v1}/examples/swap.rs | 0 anneal/{ => v1}/examples/unchecked_get.rs | 0 anneal/{ => v1}/examples/update_max.rs | 0 anneal/{ => v1}/llms-full.txt | 0 anneal/{ => v1}/llms.txt | 0 anneal/{ => v1}/src/Anneal.lean | 0 anneal/{ => v1}/src/aeneas.rs | 0 anneal/{ => v1}/src/charon.rs | 0 anneal/{ => v1}/src/diagnostics.rs | 0 anneal/{ => v1}/src/errors.rs | 0 anneal/{ => v1}/src/generate.rs | 0 anneal/v1/src/main.rs | 184 +++ anneal/{ => v1}/src/parse/attr.rs | 0 anneal/{ => v1}/src/parse/hkd.rs | 0 anneal/{ => v1}/src/parse/mod.rs | 0 anneal/{v2 => v1}/src/resolve.rs | 276 ++-- anneal/v1/src/scanner.rs | 504 ++++++ anneal/v1/src/setup.rs | 213 +++ anneal/{ => v1}/src/ui_test_shim.rs | 0 anneal/v1/src/util.rs | 59 + anneal/{ => v1}/src/validate.rs | 0 .../setup/aeneas-linux-aarch64.tar.gz | Bin .../testdata/setup/aeneas-linux-x86_64.tar.gz | Bin .../setup/aeneas-macos-aarch64.tar.gz | Bin .../testdata/setup/aeneas-macos-x86_64.tar.gz | Bin ...ls-nightly-x86_64-unknown-linux-gnu.tar.gz | Bin ...ls-nightly-x86_64-unknown-linux-gnu.tar.xz | Bin ...ri-nightly-x86_64-unknown-linux-gnu.tar.gz | Bin ...ri-nightly-x86_64-unknown-linux-gnu.tar.xz | Bin .../testdata/setup/rust-src-nightly.tar.gz | Bin .../testdata/setup/rust-src-nightly.tar.xz | Bin ...td-nightly-x86_64-unknown-linux-gnu.tar.gz | Bin ...td-nightly-x86_64-unknown-linux-gnu.tar.xz | Bin ...ev-nightly-x86_64-unknown-linux-gnu.tar.gz | Bin ...ev-nightly-x86_64-unknown-linux-gnu.tar.xz | Bin ...tc-nightly-x86_64-unknown-linux-gnu.tar.gz | Bin ...tc-nightly-x86_64-unknown-linux-gnu.tar.xz | Bin anneal/{ => v1}/tests/.gitignore | 0 .../allow_sorry_fallbacks/anneal.toml | 0 .../allow_sorry_fallbacks/expected.stderr | 0 .../allow_sorry_fallbacks/source/Cargo.toml | 0 .../allow_sorry_fallbacks/source/src/lib.rs | 0 .../anneal_multiple_targets/anneal.toml | 0 .../anneal_multiple_targets/source/Cargo.toml | 0 .../source/src/bin/my_bin.rs | 0 .../anneal_multiple_targets/source/src/lib.rs | 0 .../anneal_shim_syntax_error/anneal.toml | 0 .../anneal_shim_syntax_error/expected.stderr | 0 .../mock_charon_output.json | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../archive_lake_cache_reuse/anneal.toml | 0 .../fixtures/associated_types/anneal.toml | 0 .../fixtures/associated_types/expected.stderr | 0 .../associated_types/source/Cargo.toml | 0 .../associated_types/source/src/lib.rs | 0 .../fixtures/broken_doc_block/anneal.toml | 0 .../fixtures/broken_doc_block/expected.stderr | 0 .../broken_doc_block/source/Cargo.toml | 0 .../broken_doc_block/source/src/lib.rs | 0 .../canonicalized_workspace/anneal.toml | 0 .../canonicalized_workspace/source/Cargo.toml | 0 .../source/crates/app/Cargo.toml | 0 .../source/crates/app/src/lib.rs | 0 .../source/crates/lib/Cargo.toml | 0 .../source/crates/lib/src/lib.rs | 0 .../tests/fixtures/cfg_blind_spot/anneal.toml | 0 .../fixtures/cfg_blind_spot/expected.stderr | 0 .../fixtures/cfg_blind_spot/source/Cargo.toml | 0 .../fixtures/cfg_blind_spot/source/src/lib.rs | 0 .../fixtures/charon_version_match/anneal.toml | 0 .../charon_version_match/expected.stderr | 0 .../charon_version_match/mock_charon.sh | 0 .../charon_version_match/source/Cargo.toml | 0 .../charon_version_match/source/src/lib.rs | 0 .../tests/fixtures/collision/anneal.toml | 0 .../fixtures/collision/source/Cargo.toml | 0 .../collision/source/crates/a/Cargo.toml | 0 .../collision/source/crates/a/src/lib.rs | 0 .../collision/source/crates/b/Cargo.toml | 0 .../collision/source/crates/b/src/lib.rs | 0 .../const_block_blind_spot/anneal.toml | 0 .../const_block_blind_spot/expected.stderr | 0 .../const_block_blind_spot/source/Cargo.toml | 0 .../const_block_blind_spot/source/src/lib.rs | 0 .../tests/fixtures/const_generics/anneal.toml | 0 .../fixtures/const_generics/expected.stderr | 0 .../fixtures/const_generics/source/Cargo.toml | 0 .../fixtures/const_generics/source/src/lib.rs | 0 .../tests/fixtures/cyclic_paths/anneal.toml | 0 .../fixtures/cyclic_paths/expected.stderr | 0 .../fixtures/cyclic_paths/source/Cargo.toml | 0 .../fixtures/cyclic_paths/source/src/lib.rs | 0 .../fixtures/diagnostic_mapping/anneal.toml | 0 .../diagnostic_mapping/expected.stderr | 0 .../diagnostic_mapping/source/Cargo.toml | 0 .../diagnostic_mapping/source/src/lib.rs | 0 .../tests/fixtures/dirty_sandbox/anneal.toml | 0 .../fixtures/dirty_sandbox/source/main.rs | 0 .../fixtures/dirty_sandbox/source/target/file | 0 .../tests/fixtures/dst_layout/anneal.toml | 0 .../tests/fixtures/dst_layout/expected.stderr | 0 .../fixtures/dst_layout/source/Cargo.toml | 0 .../dst_layout/source/src/FunsExternal.lean | 0 .../fixtures/dst_layout/source/src/lib.rs | 0 .../fixtures/duplicate_blocks/anneal.toml | 0 .../fixtures/duplicate_blocks/expected.stderr | 0 .../duplicate_blocks/source/Cargo.toml | 0 .../duplicate_blocks/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_cfg/args.txt | 0 .../test_7_1_phantom_fn/anneal.toml | 0 .../test_7_1_phantom_fn/expected.stderr | 0 .../test_7_1_phantom_fn/source/Cargo.toml | 0 .../test_7_1_phantom_fn/source/src/lib.rs | 0 .../test_7_3_ghost_spec/anneal.toml | 0 .../test_7_3_ghost_spec/expected.stderr | 0 .../test_7_3_ghost_spec/source/Cargo.toml | 0 .../test_7_3_ghost_spec/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_charon/args.txt | 0 .../test_8_2_unions/anneal.toml | 0 .../test_8_2_unions/expected.stderr | 0 .../test_8_2_unions/source/Cargo.toml | 0 .../test_8_2_unions/source/src/lib.rs | 0 .../fixtures/edge_cases_control/args.txt | 0 .../fixtures/edge_cases_invariants/args.txt | 0 .../test_4_6_assoc_types/anneal.toml | 0 .../test_4_6_assoc_types/expected.stderr | 0 .../test_4_6_assoc_types/source/Cargo.toml | 0 .../test_4_6_assoc_types/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_logic/args.txt | 0 .../test_5_4_std_types/anneal.toml | 0 .../test_5_4_std_types/expected.stderr | 0 .../test_5_4_std_types/source/Cargo.toml | 0 .../test_5_4_std_types/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_macros/args.txt | 0 .../fixtures/edge_cases_modules/args.txt | 0 .../test_6_1_external_crate/anneal.toml | 0 .../test_6_1_external_crate/expected.stderr | 0 .../test_6_1_external_crate/source/Cargo.toml | 0 .../test_6_1_external_crate/source/src/lib.rs | 0 .../test_6_3_renaming/anneal.toml | 0 .../test_6_3_renaming/expected.stderr | 0 .../test_6_3_renaming/source/Cargo.toml | 0 .../test_6_3_renaming/source/src/lib.rs | 0 .../fixtures/edge_cases_mut_refs/args.txt | 0 .../test_3_3_ret_mut/anneal.toml | 0 .../test_3_3_ret_mut/expected.stderr | 0 .../test_3_3_ret_mut/source/Cargo.toml | 0 .../test_3_3_ret_mut/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_naming/args.txt | 0 .../test_1_1_lean_keywords_fns/anneal.toml | 0 .../expected.stderr | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../test_1_2_lean_keywords_args/anneal.toml | 0 .../expected.stderr | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../test_1_3_rust_keywords_idents/anneal.toml | 0 .../expected.stderr | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../tests/fixtures/edge_cases_stress/args.txt | 0 .../test_11_2_monolith/anneal.toml | 0 .../test_11_2_monolith/expected.stderr | 0 .../test_11_2_monolith/source/Cargo.toml | 0 .../test_11_2_monolith/source/src/lib.rs | 0 .../tests/fixtures/edge_cases_types/args.txt | 0 .../edge_cases_types/test_2_3_zst/anneal.toml | 0 .../test_2_3_zst/expected.stderr | 0 .../test_2_3_zst/source/Cargo.toml | 0 .../test_2_3_zst/source/src/lib.rs | 0 .../test_2_6_nested_refs/anneal.toml | 0 .../test_2_6_nested_refs/expected.stderr | 0 .../test_2_6_nested_refs/source/Cargo.toml | 0 .../test_2_6_nested_refs/source/src/lib.rs | 0 .../test_2_7_arrays/anneal.toml | 0 .../test_2_7_arrays/source/Cargo.toml | 0 .../test_2_7_arrays/source/src/lib.rs | 0 .../enums_pattern_matching/anneal.toml | 0 .../enums_pattern_matching/expected.stderr | 0 .../enums_pattern_matching/source/Cargo.toml | 0 .../enums_pattern_matching/source/src/lib.rs | 0 .../env_interleaved_stdout/anneal.toml | 0 .../env_interleaved_stdout/expected.stderr | 0 .../env_interleaved_stdout/mock_charon.sh | 0 .../mock_charon_output.json | 0 .../env_interleaved_stdout/source/Cargo.toml | 0 .../env_interleaved_stdout/source/src/lib.rs | 0 .../tests/fixtures/expand_output/anneal.toml | 0 .../expand_output/expected-aeneas.stdout | 0 .../expand_output/expected-all.stdout | 0 .../expand_output/expected-anneal.stdout | 0 .../fixtures/expand_output/source/Cargo.toml | 0 .../fixtures/expand_output/source/src/lib.rs | 0 .../extern_never_verified/anneal.toml | 0 .../fixtures/extern_never_verified/out.txt | 0 .../extern_never_verified/source/Cargo.toml | 0 .../extern_never_verified/source/src/lib.rs | 0 .../fixtures/external_dep_failure/anneal.toml | 0 .../external_dep_failure/source/Cargo.toml | 0 .../source/app/Cargo.toml | 0 .../source/app/src/lib.rs | 0 .../source/utils/Cargo.toml | 0 .../source/utils/src/lib.rs | 0 .../external_path_dependency/anneal.toml | 0 .../source/external_dep/Cargo.toml | 0 .../source/external_dep/src/lib.rs | 0 .../source/workspace/Cargo.toml | 0 .../source/workspace/app/Cargo.toml | 0 .../source/workspace/app/src/lib.rs | 0 .../fixtures/fs_missing_source/anneal.toml | 0 .../fs_missing_source/expected.stderr | 0 .../fs_missing_source/mock_charon_output.json | 0 .../fs_missing_source/source/Cargo.toml | 0 .../fs_missing_source/source/src/lib.rs | 0 .../fixtures/generate_output/anneal.toml | 0 .../generate_output/expected-generate.stdout | 0 .../generate_output/source/Cargo.toml | 0 .../generate_output/source/src/lib.rs | 0 .../fixtures/hidden_syntax_error/anneal.toml | 0 .../hidden_syntax_error/expected.stderr | 0 .../hidden_syntax_error/source/Cargo.toml | 0 .../hidden_syntax_error/source/src/lib.rs | 0 .../tests/fixtures/idempotency/anneal.toml | 0 .../fixtures/idempotency/source/Cargo.toml | 0 .../fixtures/idempotency/source/src/lib.rs | 0 .../is_valid_verification/anneal.toml | 0 .../is_valid_verification/expected.stderr | 0 .../is_valid_verification/source/Cargo.toml | 0 .../is_valid_verification/source/src/lib.rs | 0 .../json_code_suggestions/anneal.toml | 0 .../json_code_suggestions/expected.stderr | 0 .../mock_charon_output.json | 0 .../json_code_suggestions/source/Cargo.toml | 0 .../json_code_suggestions/source/src/lib.rs | 0 .../fixtures/json_linker_error/anneal.toml | 0 .../json_linker_error/expected.stderr | 0 .../json_linker_error/mock_charon_output.json | 0 .../json_linker_error/source/Cargo.toml | 0 .../json_linker_error/source/src/lib.rs | 0 .../fixtures/json_nested_children/anneal.toml | 0 .../json_nested_children/expected.stderr | 0 .../mock_charon_output.json | 0 .../json_nested_children/source/Cargo.toml | 0 .../json_nested_children/source/src/lib.rs | 0 .../fixtures/lean_edge_cases/anneal.toml | 0 .../lean_edge_cases/source/Cargo.toml | 0 .../lean_edge_cases/source/src/lib.rs | 0 .../fixtures/lean_generation/anneal.toml | 0 .../fixtures/lean_generation/expected.stderr | 0 .../lean_generation/source/Cargo.lock | 0 .../lean_generation/source/Cargo.toml | 0 .../lean_generation/source/src/lib.rs | 0 .../{ => v1}/tests/fixtures/libtest_ptr.rlib | Bin .../map_canonical_mismatch/anneal.toml | 0 .../map_canonical_mismatch/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_canonical_mismatch/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../map_canonical_mismatch/source/src/lib.rs | 0 .../source/src/macros.rs | 0 .../source/src/rewritten.rs | 0 .../source/src/symlinked.rs | 0 .../fixtures/map_external_dep/anneal.toml | 0 .../fixtures/map_external_dep/expected.stderr | 0 .../map_external_dep/mock_charon_output.json | 0 .../map_external_dep/source/Cargo.toml | 0 .../map_external_dep/source/src/lib.rs | 0 .../fixtures/map_macro_expansion/anneal.toml | 0 .../map_macro_expansion/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_macro_expansion/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../map_macro_expansion/source/src/lib.rs | 0 .../map_macro_expansion/source/src/macros.rs | 0 .../source/src/rewritten.rs | 0 .../source/src/symlinked.rs | 0 .../map_mixed_diagnostics/anneal.toml | 0 .../map_mixed_diagnostics/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_mixed_diagnostics/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../map_mixed_diagnostics/source/src/lib.rs | 0 .../source/src/macros.rs | 0 .../source/src/rewritten.rs | 0 .../source/src/symlinked.rs | 0 .../fixtures/map_path_traversal/anneal.toml | 0 .../map_path_traversal/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_path_traversal/source/Cargo.toml | 0 .../map_path_traversal/source/src/lib.rs | 0 .../fixtures/map_relative_path/anneal.toml | 0 .../map_relative_path/expected.stderr | 0 .../map_relative_path/mock_charon_output.json | 0 .../map_relative_path/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../map_relative_path/source/src/lib.rs | 0 .../map_relative_path/source/src/macros.rs | 0 .../map_relative_path/source/src/rewritten.rs | 0 .../map_relative_path/source/src/symlinked.rs | 0 .../tests/fixtures/map_std_lib/anneal.toml | 0 .../fixtures/map_std_lib/expected.stderr | 0 .../map_std_lib/mock_charon_output.json | 0 .../fixtures/map_std_lib/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../fixtures/map_std_lib/source/src/lib.rs | 0 .../fixtures/map_std_lib/source/src/macros.rs | 0 .../map_std_lib/source/src/rewritten.rs | 0 .../map_std_lib/source/src/symlinked.rs | 0 .../fixtures/map_std_library/anneal.toml | 0 .../fixtures/map_std_library/expected.stderr | 0 .../map_std_library/mock_charon_output.json | 0 .../map_std_library/source/Cargo.toml | 0 .../map_std_library/source/src/lib.rs | 0 .../fixtures/map_symlinked_file/anneal.toml | 0 .../map_symlinked_file/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_symlinked_file/source/Cargo.toml | 0 .../map_symlinked_file/source/src/lib.rs | 0 .../source/src/untransformed.rs | 0 .../map_workspace_path_dep/anneal.toml | 0 .../map_workspace_path_dep/expected.stderr | 0 .../mock_charon_output.json | 0 .../map_workspace_path_dep/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../map_workspace_path_dep/source/src/lib.rs | 0 .../source/src/macros.rs | 0 .../source/src/rewritten.rs | 0 .../source/src/symlinked.rs | 0 .../tests/fixtures/missing_output/anneal.toml | 0 .../fixtures/missing_output/expected.stderr | 0 .../fixtures/missing_output/mock_aeneas.sh | 0 .../fixtures/missing_output/source/Cargo.toml | 0 .../fixtures/missing_output/source/src/lib.rs | 0 .../fixtures/mixed_workspace/anneal.toml | 0 .../mixed_workspace/source/Cargo.toml | 0 .../source/crates/app/Cargo.toml | 0 .../source/crates/app/src/lib.rs | 0 .../source/crates/dep/Cargo.toml | 0 .../source/crates/dep/src/lib.rs | 0 .../fixtures/module_resolution/anneal.toml | 0 .../tests/fixtures/module_resolution/extra.rs | 0 .../module_resolution/source/Cargo.toml | 0 .../module_resolution/source/src/a.rs | 0 .../module_resolution/source/src/a/b.rs | 0 .../module_resolution/source/src/bar/mod.rs | 0 .../module_resolution/source/src/c.rs | 0 .../module_resolution/source/src/foo.rs | 0 .../module_resolution/source/src/lib.rs | 0 .../module_resolution/source/src/sys/unix.rs | 0 .../tests/fixtures/multi_artifact/anneal.toml | 0 .../tests/fixtures/multi_artifact/expected | 0 .../fixtures/multi_artifact/expected.stderr | 0 .../fixtures/multi_artifact/source/Cargo.toml | 0 .../fixtures/multi_artifact/source/src/lib.rs | 0 .../fixtures/multiple_errors/anneal.toml | 0 .../fixtures/multiple_errors/expected.stderr | 0 .../multiple_errors/source/Cargo.toml | 0 .../fixtures/multiple_errors/source/src/a.rs | 0 .../fixtures/multiple_errors/source/src/b.rs | 0 .../multiple_errors/source/src/lib.rs | 0 .../named_bounds_failures/anneal.toml | 0 .../named_bounds_failures/expected.stderr | 0 .../named_bounds_failures/source/Cargo.toml | 0 .../named_bounds_failures/source/src/lib.rs | 0 .../named_bounds_lean_failures/anneal.toml | 0 .../expected.stderr | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../anneal.toml | 0 .../expected.stderr | 0 .../source/Cargo.toml | 0 .../source/src/lib.rs | 0 .../fixtures/nested_item_error/anneal.toml | 0 .../nested_item_error/expected.stderr | 0 .../nested_item_error/source/Cargo.toml | 0 .../nested_item_error/source/src/lib.rs | 0 .../nested_out_of_line_mod/anneal.toml | 0 .../nested_out_of_line_mod/expected.stderr | 0 .../nested_out_of_line_mod/source/Cargo.toml | 0 .../source/src/hidden.rs | 0 .../nested_out_of_line_mod/source/src/lib.rs | 0 .../os_arg_limit_exceeded/anneal.toml | 0 .../os_arg_limit_exceeded/expected.stderr | 0 .../os_arg_limit_exceeded/source/Cargo.toml | 0 .../os_arg_limit_exceeded/source/src/lib.rs | 0 .../fixtures/raw_ptr_dst_layout/anneal.toml | 0 .../raw_ptr_dst_layout/expected.stderr | 0 .../raw_ptr_dst_layout/source/Cargo.toml | 0 .../raw_ptr_dst_layout/source/out.log | 0 .../raw_ptr_dst_layout/source/src/lib.rs | 0 .../fixtures/reject_safe_is_safe/anneal.toml | 0 .../reject_safe_is_safe/expected.stderr | 0 .../reject_safe_is_safe/source/Cargo.toml | 0 .../reject_safe_is_safe/source/src/lib.rs | 0 .../fixtures/reject_safe_requires/anneal.toml | 0 .../reject_safe_requires/expected.stderr | 0 .../reject_safe_requires/source/Cargo.toml | 0 .../reject_safe_requires/source/src/lib.rs | 0 .../tests/fixtures/select_bin/anneal.toml | 0 .../fixtures/select_bin/source/Cargo.toml | 0 .../fixtures/select_bin/source/src/lib.rs | 0 .../fixtures/select_bin/source/src/main.rs | 0 .../tests/fixtures/select_lib/anneal.toml | 0 .../fixtures/select_lib/source/Cargo.toml | 0 .../fixtures/select_lib/source/src/lib.rs | 0 .../fixtures/select_lib/source/src/main.rs | 0 .../fixtures/size_of_align_of/anneal.toml | 0 .../size_of_align_of/source/Cargo.toml | 0 .../size_of_align_of/source/src/lib.rs | 0 .../tests/fixtures/sizedness/anneal.toml | 0 .../tests/fixtures/sizedness/expected.stderr | 0 .../fixtures/sizedness/source/Cargo.toml | 0 .../tests/fixtures/sizedness/source/out.txt | 0 .../fixtures/sizedness/source/pass/Cargo.toml | 0 .../fixtures/sizedness/source/pass/src/lib.rs | 0 .../sizedness/source/reject/Cargo.toml | 0 .../sizedness/source/reject/src/lib.rs | 0 .../span_empty_unsafe_block/anneal.toml | 0 .../span_empty_unsafe_block/expected.stderr | 0 .../mock_charon_output.json | 0 .../span_empty_unsafe_block/source/Cargo.toml | 0 .../span_empty_unsafe_block/source/src/lib.rs | 0 .../source/src/untransformed.rs | 0 .../fixtures/span_macro_expansion/anneal.toml | 0 .../span_macro_expansion/expected.stderr | 0 .../mock_charon_output.json | 0 .../span_macro_expansion/source/Cargo.toml | 0 .../span_macro_expansion/source/src/lib.rs | 0 .../source/src/untransformed.rs | 0 .../fixtures/span_mapping_basic/anneal.toml | 0 .../span_mapping_basic/expected.stderr | 0 .../mock_charon_output.json | 0 .../span_mapping_basic/source/Cargo.toml | 0 .../span_mapping_basic/source/src/lib.rs | 0 .../span_multibyte_offsets/anneal.toml | 0 .../span_multibyte_offsets/expected.stderr | 0 .../mock_charon_output.json | 0 .../span_multibyte_offsets/source/Cargo.toml | 0 .../span_multibyte_offsets/source/src/lib.rs | 0 .../source/src/untransformed.rs | 0 .../tests/fixtures/split_artifact/anneal.toml | 0 .../fixtures/split_artifact/expected.stderr | 0 .../fixtures/split_artifact/source/Cargo.toml | 0 .../fixtures/split_artifact/source/src/lib.rs | 0 .../split_artifact/source/src/main.rs | 0 .../tests/fixtures/stale_output/anneal.toml | 0 .../fixtures/stale_output/source/Cargo.toml | 0 .../fixtures/stale_output/source/src/lib.rs | 0 .../tests/fixtures/stuck_wps/anneal.toml | 0 .../tests/fixtures/stuck_wps/expected.stderr | 0 .../fixtures/stuck_wps/source/Cargo.toml | 0 .../stuck_wps/source/crates/app/Cargo.toml | 0 .../stuck_wps/source/crates/app/src/lib.rs | 0 .../stuck_wps/source/crates/dep/Cargo.toml | 0 .../stuck_wps/source/crates/dep/src/lib.rs | 0 .../fixtures/success_allow_sorry/anneal.toml | 0 .../success_allow_sorry/source/Cargo.toml | 0 .../source/src/cfg_and_macros.rs | 0 .../cfg_and_macros/macro_blind_spot/hidden.rs | 0 .../warn_cfg_attr_path/sys_unix.rs | 0 .../source/src/hierarchy_and_stress.rs | 0 .../deep_invocation/nested.rs | 0 .../success_allow_sorry/source/src/lib.rs | 0 .../source/src/logic_and_patterns.rs | 0 .../source/src/naming_and_imports.rs | 0 .../source/src/primitives.rs | 0 .../success_allow_sorry/source/src/types.rs | 0 .../success_allow_sorry_is_valid/anneal.toml | 0 .../source/Cargo.toml | 0 .../source/src/framework.rs | 0 .../source/src/lib.rs | 0 .../source/src/logic_and_control.rs | 0 .../source/src/macro_checks.rs | 0 .../source/src/memory_and_borrows.rs | 0 .../source/src/spec_syntax.rs | 0 .../source/src/traits_and_impls.rs | 0 .../source/src/types_and_data.rs | 0 .../tests/fixtures/syntax_error/anneal.toml | 0 .../fixtures/syntax_error/expected.stderr | 0 .../fixtures/syntax_error/source/Cargo.toml | 0 .../fixtures/syntax_error/source/src/lib.rs | 0 .../fixtures/target_selection/anneal.toml | 0 .../fixtures/target_selection/expected.stderr | 0 .../target_selection/source/Cargo.toml | 0 .../target_selection/source/src/lib.rs | 0 .../target_selection/source/src/main.rs | 0 .../tests/fixtures/test_ptr_crate/Cargo.toml | 0 .../tests/fixtures/test_ptr_crate/src/lib.rs | 0 .../tests/fixtures/type_features/anneal.toml | 0 .../fixtures/type_features/expected.stderr | 0 .../fixtures/type_features/source/Cargo.toml | 0 .../fixtures/type_features/source/src/lib.rs | 0 .../ui_build_script_noise/anneal.toml | 0 .../ui_build_script_noise/expected.stderr | 0 .../mock_charon_output.json | 0 .../ui_build_script_noise/source/Cargo.toml | 0 .../ui_build_script_noise/source/src/lib.rs | 0 .../fixtures/ui_hanging_build/anneal.toml | 0 .../fixtures/ui_hanging_build/expected.stderr | 0 .../ui_hanging_build/source/Cargo.toml | 0 .../fixtures/ui_hanging_build/source/build.rs | 0 .../ui_hanging_build/source/src/lib.rs | 0 .../fixtures/ui_silent_panic/anneal.toml | 0 .../fixtures/ui_silent_panic/expected.stderr | 0 .../ui_silent_panic/source/Cargo.toml | 0 .../fixtures/ui_silent_panic/source/build.rs | 0 .../ui_silent_panic/source/src/lib.rs | 0 .../tests/fixtures/ui_the_flood/anneal.toml | 0 .../fixtures/ui_the_flood/expected.stderr | 0 .../ui_the_flood/mock_charon_output.json | 0 .../fixtures/ui_the_flood/source/Cargo.toml | 0 .../fixtures/ui_the_flood/source/src/lib.rs | 0 .../fixtures/ui_visual_ghosting/anneal.toml | 0 .../ui_visual_ghosting/expected.stderr | 0 .../mock_charon_output.json | 0 .../ui_visual_ghosting/source/Cargo.toml | 0 .../ui_visual_ghosting/source/src/lib.rs | 0 .../tests/fixtures/unions/anneal.toml | 0 .../tests/fixtures/unions/expected.stderr | 0 .../tests/fixtures/unions/source/Cargo.toml | 0 .../tests/fixtures/unions/source/src/lib.rs | 0 .../unsound_is_valid_error/anneal.toml | 0 .../unsound_is_valid_error/expected.stderr | 0 .../unsound_is_valid_error/source/Cargo.toml | 0 .../unsound_is_valid_error/source/src/lib.rs | 0 .../verify_is_valid_macro/anneal.toml | 0 .../verify_is_valid_macro/source/Cargo.toml | 0 .../verify_is_valid_macro/source/src/lib.rs | 0 .../fixtures/warnings_vs_errors/anneal.toml | 0 .../warnings_vs_errors/expected.stderr | 0 .../mock_charon_output.json | 0 .../warnings_vs_errors/source/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 .../warnings_vs_errors/source/src/lib.rs | 0 .../warnings_vs_errors/source/src/macros.rs | 0 .../source/src/rewritten.rs | 0 .../source/src/symlinked.rs | 0 .../fixtures/weird_functions/anneal.toml | 0 .../fixtures/weird_functions/expected.stderr | 0 .../weird_functions/source/Cargo.toml | 0 .../weird_functions/source/src/lib.rs | 0 .../fixtures/workspace_path_dep/args.txt | 0 .../workspace_path_dep/source/Cargo.toml | 0 .../source/crates/app/Cargo.toml | 0 .../source/crates/app/src/lib.rs | 0 .../source/crates/utils/Cargo.toml | 0 .../source/crates/utils/src/lib.rs | 0 anneal/{ => v1}/tests/integration.rs | 0 anneal/{ => v1}/tests/ui.rs | 0 anneal/{ => v1}/tests/ui/fail_precondition.rs | 0 .../tests/ui/fail_precondition.stderr | 0 anneal/{ => v1}/tests/ui/fail_syntax.rs | 0 anneal/{ => v1}/tests/ui/fail_syntax.stderr | 0 anneal/{ => v1}/tests/ui/pass_simple.rs | 0 .../tools/check-release-flow-dry-run.sh | 44 +- .../{ => v1}/tools/check-release-pr-files.py | 0 .../tools/collect-release-archive-metadata.py | 0 anneal/{ => v1}/tools/doc_gen/Cargo.toml | 0 anneal/{ => v1}/tools/doc_gen/src/main.rs | 0 anneal/{ => v1}/tools/pre-publish.sh | 2 +- anneal/{ => v1}/tools/prune_mathlib.py | 0 .../tools/test_exocrate_metadata_helpers.py | 0 .../{ => v1}/tools/test_release_pr_files.py | 14 +- .../tools/update-exocrate-metadata.py | 4 +- anneal/v2/Cargo.toml | 69 - anneal/v2/src/main.rs | 342 ---- anneal/v2/src/scanner.rs | 102 -- anneal/v2/src/setup.rs | 154 -- anneal/v2/src/util.rs | 283 ---- ci/check_fmt.sh | 2 +- ci/release_anneal_version.sh | 8 +- hermes | 2 +- tools/hermes | 2 +- 631 files changed, 3565 insertions(+), 3565 deletions(-) delete mode 120000 anneal/LICENSE-APACHE delete mode 120000 anneal/LICENSE-BSD delete mode 120000 anneal/LICENSE-MIT rename anneal/{v2 => }/chase-aeneas-versions.sh (100%) rename anneal/{v2 => }/check-flake-eval.sh (98%) rename anneal/{v2 => }/flake.lock (100%) rename anneal/{v2 => }/flake.nix (100%) rename anneal/{v2 => }/prune-lake-cache.py (100%) rename anneal/{v2 => }/rewrite-lake-vendor.py (100%) rename anneal/{v2 => }/tests/test_prune_lake_cache.py (100%) rename anneal/{v2 => }/tests/test_rewrite_lake_vendor.py (100%) rename anneal/{ => v1}/.gitattributes (100%) rename anneal/{ => v1}/.gitignore (100%) rename anneal/{ => v1}/AGENTS.md (100%) rename anneal/{v2 => v1}/Cargo.lock (68%) create mode 100644 anneal/v1/Cargo.toml rename anneal/{ => v1}/Dockerfile (94%) create mode 120000 anneal/v1/LICENSE-APACHE create mode 120000 anneal/v1/LICENSE-BSD create mode 120000 anneal/v1/LICENSE-MIT rename anneal/{ => v1}/README.md (100%) rename anneal/{ => v1}/build.rs (100%) rename anneal/{ => v1}/docker.sh (97%) rename anneal/{ => v1}/docs/agent/01_philosophy_and_pipeline.md (100%) rename anneal/{ => v1}/docs/agent/02_rust_to_lean_mapping.md (100%) rename anneal/{ => v1}/docs/agent/03_memory_model.md (100%) rename anneal/{ => v1}/docs/agent/04_specifications_and_syntax.md (100%) rename anneal/{ => v1}/docs/agent/05_proof_architecture.md (100%) rename anneal/{ => v1}/docs/agent/06_tactics_and_tooling.md (100%) rename anneal/{ => v1}/docs/agent/07_workflow.md (100%) rename anneal/{ => v1}/docs/design/design.md (100%) rename anneal/{ => v1}/docs/design/named_bounds.md (100%) rename anneal/{ => v1}/docs/images/logo.svg (100%) rename anneal/{ => v1}/examples/abs.rs (100%) rename anneal/{ => v1}/examples/anatomy.rs (100%) rename anneal/{ => v1}/examples/checked_add.rs (100%) rename anneal/{ => v1}/examples/const_generics.rs (100%) rename anneal/{ => v1}/examples/design_doc.rs (100%) rename anneal/{ => v1}/examples/linked_list.rs (100%) rename anneal/{ => v1}/examples/namespaces.rs (100%) rename anneal/{ => v1}/examples/never_type.rs (100%) rename anneal/{ => v1}/examples/nopanic.rs (100%) rename anneal/{ => v1}/examples/positive_usize.rs (100%) rename anneal/{ => v1}/examples/ptr_concat.rs (100%) rename anneal/{ => v1}/examples/size_of_align_of.rs (100%) rename anneal/{ => v1}/examples/swap.rs (100%) rename anneal/{ => v1}/examples/unchecked_get.rs (100%) rename anneal/{ => v1}/examples/update_max.rs (100%) rename anneal/{ => v1}/llms-full.txt (100%) rename anneal/{ => v1}/llms.txt (100%) rename anneal/{ => v1}/src/Anneal.lean (100%) rename anneal/{ => v1}/src/aeneas.rs (100%) rename anneal/{ => v1}/src/charon.rs (100%) rename anneal/{ => v1}/src/diagnostics.rs (100%) rename anneal/{ => v1}/src/errors.rs (100%) rename anneal/{ => v1}/src/generate.rs (100%) create mode 100644 anneal/v1/src/main.rs rename anneal/{ => v1}/src/parse/attr.rs (100%) rename anneal/{ => v1}/src/parse/hkd.rs (100%) rename anneal/{ => v1}/src/parse/mod.rs (100%) rename anneal/{v2 => v1}/src/resolve.rs (61%) create mode 100644 anneal/v1/src/scanner.rs create mode 100644 anneal/v1/src/setup.rs rename anneal/{ => v1}/src/ui_test_shim.rs (100%) create mode 100644 anneal/v1/src/util.rs rename anneal/{ => v1}/src/validate.rs (100%) rename anneal/{ => v1}/testdata/setup/aeneas-linux-aarch64.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/aeneas-linux-x86_64.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/aeneas-macos-aarch64.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/aeneas-macos-x86_64.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz (100%) rename anneal/{ => v1}/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.xz (100%) rename anneal/{ => v1}/testdata/setup/rust-src-nightly.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/rust-src-nightly.tar.xz (100%) rename anneal/{ => v1}/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz (100%) rename anneal/{ => v1}/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.xz (100%) rename anneal/{ => v1}/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz (100%) rename anneal/{ => v1}/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz (100%) rename anneal/{ => v1}/tests/.gitignore (100%) rename anneal/{ => v1}/tests/fixtures/allow_sorry_fallbacks/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/allow_sorry_fallbacks/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/allow_sorry_fallbacks/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/allow_sorry_fallbacks/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/anneal_multiple_targets/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/anneal_multiple_targets/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/anneal_multiple_targets/source/src/bin/my_bin.rs (100%) rename anneal/{ => v1}/tests/fixtures/anneal_multiple_targets/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/anneal_shim_syntax_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/anneal_shim_syntax_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/anneal_shim_syntax_error/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/anneal_shim_syntax_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/anneal_shim_syntax_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/archive_lake_cache_reuse/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/associated_types/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/associated_types/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/associated_types/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/associated_types/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/broken_doc_block/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/broken_doc_block/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/broken_doc_block/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/broken_doc_block/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/source/crates/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/source/crates/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/source/crates/lib/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/canonicalized_workspace/source/crates/lib/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/cfg_blind_spot/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/cfg_blind_spot/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/cfg_blind_spot/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/cfg_blind_spot/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/charon_version_match/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/charon_version_match/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/charon_version_match/mock_charon.sh (100%) rename anneal/{ => v1}/tests/fixtures/charon_version_match/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/charon_version_match/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/collision/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/collision/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/collision/source/crates/a/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/collision/source/crates/a/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/collision/source/crates/b/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/collision/source/crates/b/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/const_block_blind_spot/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/const_block_blind_spot/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/const_block_blind_spot/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/const_block_blind_spot/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/const_generics/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/const_generics/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/const_generics/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/const_generics/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/cyclic_paths/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/cyclic_paths/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/cyclic_paths/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/cyclic_paths/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/diagnostic_mapping/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/diagnostic_mapping/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/diagnostic_mapping/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/diagnostic_mapping/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/dirty_sandbox/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/dirty_sandbox/source/main.rs (100%) rename anneal/{ => v1}/tests/fixtures/dirty_sandbox/source/target/file (100%) rename anneal/{ => v1}/tests/fixtures/dst_layout/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/dst_layout/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/dst_layout/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/dst_layout/source/src/FunsExternal.lean (100%) rename anneal/{ => v1}/tests/fixtures/dst_layout/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/duplicate_blocks/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/duplicate_blocks/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/duplicate_blocks/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/duplicate_blocks/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_charon/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_charon/test_8_2_unions/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_charon/test_8_2_unions/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_charon/test_8_2_unions/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_charon/test_8_2_unions/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_control/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_invariants/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_logic/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_logic/test_5_4_std_types/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_logic/test_5_4_std_types/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_macros/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_1_external_crate/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_1_external_crate/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_3_renaming/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_3_renaming/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_mut_refs/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_stress/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_stress/test_11_2_monolith/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_stress/test_11_2_monolith/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_3_zst/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_3_zst/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_3_zst/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_3_zst/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_6_nested_refs/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_6_nested_refs/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_7_arrays/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_7_arrays/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/edge_cases_types/test_2_7_arrays/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/enums_pattern_matching/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/enums_pattern_matching/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/enums_pattern_matching/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/enums_pattern_matching/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/mock_charon.sh (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/env_interleaved_stdout/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/expected-aeneas.stdout (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/expected-all.stdout (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/expected-anneal.stdout (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/expand_output/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/extern_never_verified/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/extern_never_verified/out.txt (100%) rename anneal/{ => v1}/tests/fixtures/extern_never_verified/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/extern_never_verified/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/source/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/source/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/source/utils/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_dep_failure/source/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/source/external_dep/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/source/external_dep/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/source/workspace/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/source/workspace/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/external_path_dependency/source/workspace/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/fs_missing_source/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/fs_missing_source/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/fs_missing_source/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/fs_missing_source/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/fs_missing_source/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/generate_output/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/generate_output/expected-generate.stdout (100%) rename anneal/{ => v1}/tests/fixtures/generate_output/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/generate_output/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/hidden_syntax_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/hidden_syntax_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/hidden_syntax_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/hidden_syntax_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/idempotency/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/idempotency/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/idempotency/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/is_valid_verification/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/is_valid_verification/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/is_valid_verification/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/is_valid_verification/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/json_code_suggestions/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_code_suggestions/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/json_code_suggestions/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/json_code_suggestions/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_code_suggestions/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/json_linker_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_linker_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/json_linker_error/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/json_linker_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_linker_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/json_nested_children/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_nested_children/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/json_nested_children/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/json_nested_children/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/json_nested_children/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/lean_edge_cases/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/lean_edge_cases/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/lean_edge_cases/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/lean_generation/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/lean_generation/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/lean_generation/source/Cargo.lock (100%) rename anneal/{ => v1}/tests/fixtures/lean_generation/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/lean_generation/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/libtest_ptr.rlib (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_canonical_mismatch/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_external_dep/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_external_dep/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_external_dep/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_external_dep/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_external_dep/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_macro_expansion/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_mixed_diagnostics/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_path_traversal/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_path_traversal/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_path_traversal/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_path_traversal/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_path_traversal/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_relative_path/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_lib/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_std_library/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_std_library/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_std_library/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_std_library/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_std_library/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_symlinked_file/source/src/untransformed.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/map_workspace_path_dep/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/missing_output/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/missing_output/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/missing_output/mock_aeneas.sh (100%) rename anneal/{ => v1}/tests/fixtures/missing_output/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/missing_output/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/source/crates/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/source/crates/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/source/crates/dep/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/mixed_workspace/source/crates/dep/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/extra.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/a.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/a/b.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/bar/mod.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/c.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/foo.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/module_resolution/source/src/sys/unix.rs (100%) rename anneal/{ => v1}/tests/fixtures/multi_artifact/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/multi_artifact/expected (100%) rename anneal/{ => v1}/tests/fixtures/multi_artifact/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/multi_artifact/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/multi_artifact/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/source/src/a.rs (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/source/src/b.rs (100%) rename anneal/{ => v1}/tests/fixtures/multiple_errors/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_failures/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_failures/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_failures/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_failures/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_lean_failures/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_lean_failures/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_lean_failures/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_lean_failures/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_validation_failures/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_validation_failures/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_validation_failures/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/named_bounds_validation_failures/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/nested_item_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/nested_item_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/nested_item_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/nested_item_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/nested_out_of_line_mod/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/nested_out_of_line_mod/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/nested_out_of_line_mod/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/nested_out_of_line_mod/source/src/hidden.rs (100%) rename anneal/{ => v1}/tests/fixtures/nested_out_of_line_mod/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/os_arg_limit_exceeded/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/os_arg_limit_exceeded/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/os_arg_limit_exceeded/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/os_arg_limit_exceeded/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/raw_ptr_dst_layout/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/raw_ptr_dst_layout/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/raw_ptr_dst_layout/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/raw_ptr_dst_layout/source/out.log (100%) rename anneal/{ => v1}/tests/fixtures/raw_ptr_dst_layout/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_is_safe/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_is_safe/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_is_safe/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_is_safe/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_requires/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_requires/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_requires/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/reject_safe_requires/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/select_bin/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/select_bin/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/select_bin/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/select_bin/source/src/main.rs (100%) rename anneal/{ => v1}/tests/fixtures/select_lib/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/select_lib/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/select_lib/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/select_lib/source/src/main.rs (100%) rename anneal/{ => v1}/tests/fixtures/size_of_align_of/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/size_of_align_of/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/size_of_align_of/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/out.txt (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/pass/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/pass/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/reject/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/sizedness/source/reject/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_empty_unsafe_block/source/src/untransformed.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_macro_expansion/source/src/untransformed.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_mapping_basic/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_mapping_basic/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/span_mapping_basic/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/span_mapping_basic/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_mapping_basic/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/span_multibyte_offsets/source/src/untransformed.rs (100%) rename anneal/{ => v1}/tests/fixtures/split_artifact/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/split_artifact/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/split_artifact/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/split_artifact/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/split_artifact/source/src/main.rs (100%) rename anneal/{ => v1}/tests/fixtures/stale_output/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/stale_output/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/stale_output/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/source/crates/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/source/crates/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/source/crates/dep/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/stuck_wps/source/crates/dep/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/macro_blind_spot/hidden.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/warn_cfg_attr_path/sys_unix.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress/deep_invocation/nested.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/logic_and_patterns.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/naming_and_imports.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/primitives.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry/source/src/types.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/framework.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/logic_and_control.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/macro_checks.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/memory_and_borrows.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/spec_syntax.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/traits_and_impls.rs (100%) rename anneal/{ => v1}/tests/fixtures/success_allow_sorry_is_valid/source/src/types_and_data.rs (100%) rename anneal/{ => v1}/tests/fixtures/syntax_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/syntax_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/syntax_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/syntax_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/target_selection/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/target_selection/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/target_selection/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/target_selection/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/target_selection/source/src/main.rs (100%) rename anneal/{ => v1}/tests/fixtures/test_ptr_crate/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/test_ptr_crate/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/type_features/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/type_features/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/type_features/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/type_features/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_build_script_noise/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_build_script_noise/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/ui_build_script_noise/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/ui_build_script_noise/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_build_script_noise/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_hanging_build/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_hanging_build/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/ui_hanging_build/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_hanging_build/source/build.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_hanging_build/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_silent_panic/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_silent_panic/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/ui_silent_panic/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_silent_panic/source/build.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_silent_panic/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_the_flood/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_the_flood/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/ui_the_flood/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/ui_the_flood/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_the_flood/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/ui_visual_ghosting/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_visual_ghosting/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/ui_visual_ghosting/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/ui_visual_ghosting/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/ui_visual_ghosting/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/unions/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/unions/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/unions/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/unions/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/unsound_is_valid_error/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/unsound_is_valid_error/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/unsound_is_valid_error/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/unsound_is_valid_error/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/verify_is_valid_macro/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/verify_is_valid_macro/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/verify_is_valid_macro/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/mock_charon_output.json (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/src/macros.rs (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/src/rewritten.rs (100%) rename anneal/{ => v1}/tests/fixtures/warnings_vs_errors/source/src/symlinked.rs (100%) rename anneal/{ => v1}/tests/fixtures/weird_functions/anneal.toml (100%) rename anneal/{ => v1}/tests/fixtures/weird_functions/expected.stderr (100%) rename anneal/{ => v1}/tests/fixtures/weird_functions/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/weird_functions/source/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/args.txt (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/source/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/source/crates/app/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/source/crates/app/src/lib.rs (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/source/crates/utils/Cargo.toml (100%) rename anneal/{ => v1}/tests/fixtures/workspace_path_dep/source/crates/utils/src/lib.rs (100%) rename anneal/{ => v1}/tests/integration.rs (100%) rename anneal/{ => v1}/tests/ui.rs (100%) rename anneal/{ => v1}/tests/ui/fail_precondition.rs (100%) rename anneal/{ => v1}/tests/ui/fail_precondition.stderr (100%) rename anneal/{ => v1}/tests/ui/fail_syntax.rs (100%) rename anneal/{ => v1}/tests/ui/fail_syntax.stderr (100%) rename anneal/{ => v1}/tests/ui/pass_simple.rs (100%) rename anneal/{ => v1}/tools/check-release-flow-dry-run.sh (83%) rename anneal/{ => v1}/tools/check-release-pr-files.py (100%) rename anneal/{ => v1}/tools/collect-release-archive-metadata.py (100%) rename anneal/{ => v1}/tools/doc_gen/Cargo.toml (100%) rename anneal/{ => v1}/tools/doc_gen/src/main.rs (100%) rename anneal/{ => v1}/tools/pre-publish.sh (86%) rename anneal/{ => v1}/tools/prune_mathlib.py (100%) rename anneal/{ => v1}/tools/test_exocrate_metadata_helpers.py (100%) rename anneal/{ => v1}/tools/test_release_pr_files.py (69%) rename anneal/{ => v1}/tools/update-exocrate-metadata.py (97%) delete mode 100644 anneal/v2/Cargo.toml delete mode 100644 anneal/v2/src/main.rs delete mode 100644 anneal/v2/src/scanner.rs delete mode 100644 anneal/v2/src/setup.rs delete mode 100644 anneal/v2/src/util.rs diff --git a/.dockerignore b/.dockerignore index 4137355cec..f63645e591 100644 --- a/.dockerignore +++ b/.dockerignore @@ -10,7 +10,7 @@ /target/ /zerocopy/target/ /anneal/target/ -/anneal/v2/target/ +/anneal/v1/target/ /tools/target/ /exocrate/target/ /hermes/target/ diff --git a/.github/workflows/anneal-release.yml b/.github/workflows/anneal-release.yml index 4e20570434..73eaf60086 100644 --- a/.github/workflows/anneal-release.yml +++ b/.github/workflows/anneal-release.yml @@ -13,7 +13,7 @@ on: branches: - main paths: - - 'anneal/Cargo.toml' + - 'anneal/v1/Cargo.toml' workflow_dispatch: inputs: version: @@ -54,7 +54,7 @@ jobs: id: check run: | set -eo pipefail - cd anneal + cd anneal/v1 CUR_VER=$(cargo metadata -q --format-version 1 | jq -r '.packages[] | select(.name == "cargo-anneal").version') @@ -96,7 +96,7 @@ jobs: CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} run: | set -eo pipefail - cd anneal + cd anneal/v1 ./tools/pre-publish.sh cargo publish --allow-dirty --registry crates-io @@ -150,13 +150,13 @@ jobs: ./ci/release_anneal_version.sh "$VERSION" - python3 anneal/tools/check-release-pr-files.py \ + python3 anneal/v1/tools/check-release-pr-files.py \ --context "Release version bump" \ --include-untracked \ - --allowed anneal/Cargo.lock \ - --allowed anneal/Cargo.toml \ - --allowed anneal/README.md \ - --required anneal/Cargo.toml + --allowed anneal/v1/Cargo.lock \ + --allowed anneal/v1/Cargo.toml \ + --allowed anneal/v1/README.md \ + --required anneal/v1/Cargo.toml git diff --binary > anneal-release-source.patch if [ ! -s anneal-release-source.patch ]; then @@ -284,33 +284,33 @@ jobs: set -eo pipefail ARCHIVE_NAME="anneal-toolchain-${TARGET}.tar.zst" MAX_GITHUB_RELEASE_ASSET_SIZE=2147483647 - mkdir -p anneal/v2/target anneal/release-download-check anneal/release-metadata + mkdir -p anneal/target anneal/v1/release-download-check anneal/v1/release-metadata - nix build ./anneal/v2#omnibus-archive-ci --out-link "anneal/v2/target/${ARCHIVE_NAME}" - cp -L "anneal/v2/target/${ARCHIVE_NAME}" "anneal/${ARCHIVE_NAME}" - ARCHIVE_SIZE="$(python3 -c 'import os, sys; print(os.path.getsize(sys.argv[1]))' "anneal/${ARCHIVE_NAME}")" + nix build ./anneal#omnibus-archive-ci --out-link "anneal/target/${ARCHIVE_NAME}" + cp -L "anneal/target/${ARCHIVE_NAME}" "anneal/v1/${ARCHIVE_NAME}" + ARCHIVE_SIZE="$(python3 -c 'import os, sys; print(os.path.getsize(sys.argv[1]))' "anneal/v1/${ARCHIVE_NAME}")" printf 'Built %s (%s bytes)\n' "$ARCHIVE_NAME" "$ARCHIVE_SIZE" if [ "$ARCHIVE_SIZE" -gt "$MAX_GITHUB_RELEASE_ASSET_SIZE" ]; then echo "::error::${ARCHIVE_NAME} is ${ARCHIVE_SIZE} bytes, which exceeds GitHub's ${MAX_GITHUB_RELEASE_ASSET_SIZE}-byte release asset limit." exit 1 fi - gh release upload "$TAG_NAME" "anneal/${ARCHIVE_NAME}" --repo "$GH_REPO" --clobber + gh release upload "$TAG_NAME" "anneal/v1/${ARCHIVE_NAME}" --repo "$GH_REPO" --clobber gh release download "$TAG_NAME" \ --repo "$GH_REPO" \ --pattern "$ARCHIVE_NAME" \ - --dir anneal/release-download-check \ + --dir anneal/v1/release-download-check \ --clobber - cmp "anneal/${ARCHIVE_NAME}" "anneal/release-download-check/${ARCHIVE_NAME}" + cmp "anneal/v1/${ARCHIVE_NAME}" "anneal/v1/release-download-check/${ARCHIVE_NAME}" url="https://github.com/${GH_REPO}/releases/download/${TAG_NAME}/${ARCHIVE_NAME}" - python3 anneal/tools/collect-release-archive-metadata.py \ - --archive "anneal/release-download-check/${ARCHIVE_NAME}" \ + python3 anneal/v1/tools/collect-release-archive-metadata.py \ + --archive "anneal/v1/release-download-check/${ARCHIVE_NAME}" \ --target "$TARGET" \ --os "$CARGO_OS" \ --arch "$CARGO_ARCH" \ --url "$url" \ - --out "anneal/release-metadata/${TARGET}.json" + --out "anneal/v1/release-metadata/${TARGET}.json" - name: Restore AppArmor restriction if: always() && runner.os == 'Linux' @@ -320,7 +320,7 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: anneal-toolchain-metadata-${{ matrix.target }} - path: anneal/release-metadata/${{ matrix.target }}.json + path: anneal/v1/release-metadata/${{ matrix.target }}.json if-no-files-found: error retention-days: 1 @@ -359,7 +359,7 @@ jobs: uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: anneal-toolchain-metadata-* - path: anneal/release-metadata + path: anneal/v1/release-metadata merge-multiple: true - name: Update Anneal archive metadata @@ -367,27 +367,27 @@ jobs: TAG_NAME: ${{ needs.create-release.outputs.tag_name }} run: | set -eo pipefail - python3 anneal/tools/update-exocrate-metadata.py \ - --cargo-toml anneal/Cargo.toml \ - --metadata-dir anneal/release-metadata \ + python3 anneal/v1/tools/update-exocrate-metadata.py \ + --cargo-toml anneal/v1/Cargo.toml \ + --metadata-dir anneal/v1/release-metadata \ --expected-release-tag "$TAG_NAME" \ --require-all rm -f anneal-release-source.patch - rm -rf anneal/release-metadata + rm -rf anneal/v1/release-metadata - python3 anneal/tools/check-release-pr-files.py \ + python3 anneal/v1/tools/check-release-pr-files.py \ --context "Release workflow" \ --include-untracked \ - --allowed anneal/Cargo.lock \ - --allowed anneal/Cargo.toml \ - --allowed anneal/README.md \ - --required anneal/Cargo.toml + --allowed anneal/v1/Cargo.lock \ + --allowed anneal/v1/Cargo.toml \ + --allowed anneal/v1/README.md \ + --required anneal/v1/Cargo.toml - name: Submit PR id: submit-pr-upstream if: github.repository == 'google/zerocopy' - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.0 # zizmor: ignore[superfluous-actions] + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 # zizmor: ignore[superfluous-actions] with: commit-message: "Release Anneal ${{ github.event.inputs.version }}" author: Google PR Creation Bot @@ -396,16 +396,16 @@ jobs: base: ${{ github.event.inputs.branch }} branch: anneal-release-${{ github.event.inputs.version }} add-paths: | - anneal/Cargo.lock - anneal/Cargo.toml - anneal/README.md + anneal/v1/Cargo.lock + anneal/v1/Cargo.toml + anneal/v1/README.md push-to-fork: google-pr-creation-bot/zerocopy token: ${{ secrets.GOOGLE_PR_CREATION_BOT_TOKEN }} # zizmor: ignore[secrets-outside-env] - name: Submit PR (fork test) id: submit-pr-fork if: github.repository != 'google/zerocopy' - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.0 # zizmor: ignore[superfluous-actions] + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 # zizmor: ignore[superfluous-actions] with: commit-message: "Release Anneal ${{ github.event.inputs.version }}" author: Google PR Creation Bot @@ -414,9 +414,9 @@ jobs: base: ${{ github.event.inputs.branch }} branch: anneal-release-${{ github.event.inputs.version }} add-paths: | - anneal/Cargo.lock - anneal/Cargo.toml - anneal/README.md + anneal/v1/Cargo.lock + anneal/v1/Cargo.toml + anneal/v1/README.md token: ${{ github.token }} - name: Add labels diff --git a/.github/workflows/anneal.yml b/.github/workflows/anneal.yml index 9b6c95ce40..7c0697b0ab 100644 --- a/.github/workflows/anneal.yml +++ b/.github/workflows/anneal.yml @@ -50,33 +50,33 @@ jobs: set -euo pipefail export PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile \ - anneal/tools/check-release-pr-files.py \ - anneal/tools/test_exocrate_metadata_helpers.py \ - anneal/tools/test_release_pr_files.py \ - anneal/tools/collect-release-archive-metadata.py \ - anneal/tools/update-exocrate-metadata.py \ - anneal/v2/tests/test_prune_lake_cache.py \ - anneal/v2/prune-lake-cache.py \ - anneal/v2/rewrite-lake-vendor.py - python3 -m unittest discover -s anneal/tools -p 'test_*.py' - python3 -m unittest discover -s anneal/v2/tests -p 'test_*.py' - bash anneal/tools/check-release-flow-dry-run.sh + anneal/v1/tools/check-release-pr-files.py \ + anneal/v1/tools/test_exocrate_metadata_helpers.py \ + anneal/v1/tools/test_release_pr_files.py \ + anneal/v1/tools/collect-release-archive-metadata.py \ + anneal/v1/tools/update-exocrate-metadata.py \ + anneal/tests/test_prune_lake_cache.py \ + anneal/prune-lake-cache.py \ + anneal/rewrite-lake-vendor.py + python3 -m unittest discover -s anneal/v1/tools -p 'test_*.py' + python3 -m unittest discover -s anneal/tests -p 'test_*.py' + bash anneal/v1/tools/check-release-flow-dry-run.sh - name: Install Nix uses: DeterminateSystems/determinate-nix-action@d96678350ffd6a456235832eb11e1c491589b7bb # v3.21.8 - name: Check V2 flake evaluation - run: bash anneal/v2/check-flake-eval.sh + run: bash anneal/check-flake-eval.sh anneal_tests: - name: Anneal Tests + name: Anneal V1 Tests runs-on: ubuntu-latest needs: v2_nix_cache permissions: actions: read # Required to download the toolchain artifact. contents: write # Required to push benchmark data to the storage branch env: - ANNEAL_TOOLCHAIN_DIR: ${{ github.workspace }}/anneal/target/anneal-toolchain + ANNEAL_TOOLCHAIN_DIR: ${{ github.workspace }}/anneal/v1/target/anneal-toolchain __ZEROCOPY_LOCAL_DEV: 1 RUSTFLAGS: "" RUSTDOCFLAGS: "" @@ -99,16 +99,16 @@ jobs: uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: anneal-exocrate.tar.zst - path: anneal/v2/target + path: anneal/target # Ensure `llms-full.txt` file is up-to-date. - name: Check doc generation run: cargo run -p doc_gen -- --check - working-directory: anneal + working-directory: anneal/v1 - name: Install Anneal toolchain archive - run: cargo run setup --local-archive v2/target/anneal-exocrate.tar.zst - working-directory: anneal + run: cargo run setup --local-archive ../target/anneal-exocrate.tar.zst + working-directory: anneal/v1 # Run unit tests separately, as they're much less likely to have bugs # during local development, and this makes the GitHub Actions output @@ -116,7 +116,7 @@ jobs: # is due to unit or integration tests). - name: Run unit tests run: cargo test --verbose --bin cargo-anneal - working-directory: anneal + working-directory: anneal/v1 # We duplicate running unit tests since they're very cheap compared to # integration tests, and this way it's easier to be sure that we run all @@ -130,7 +130,7 @@ jobs: duration=$((end - start)) echo "Test Time: $duration seconds" echo "[{\"name\": \"Test Time\", \"unit\": \"seconds\", \"value\": $duration}]" > test_time.json - working-directory: anneal + working-directory: anneal/v1 - name: Combine benchmarks env: @@ -141,7 +141,7 @@ jobs: echo "[{\"name\": \"Total CI Duration (All Steps)\", \"unit\": \"seconds\", \"value\": $total_duration}]" > total_time.json jq -n \ - --slurpfile test anneal/test_time.json \ + --slurpfile test anneal/v1/test_time.json \ --slurpfile total total_time.json \ '[ $test[0][0], @@ -167,14 +167,14 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} verify_examples: - name: Verify example (${{ matrix.example }}) + name: Verify V1 example (${{ matrix.example }}) runs-on: ubuntu-latest needs: v2_nix_cache permissions: actions: read # Required to download the toolchain artifact. contents: read env: - ANNEAL_TOOLCHAIN_DIR: ${{ github.workspace }}/anneal/target/anneal-toolchain + ANNEAL_TOOLCHAIN_DIR: ${{ github.workspace }}/anneal/v1/target/anneal-toolchain __ZEROCOPY_LOCAL_DEV: 1 RUSTFLAGS: "" RUSTDOCFLAGS: "" @@ -215,11 +215,11 @@ jobs: uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: anneal-exocrate.tar.zst - path: anneal/v2/target + path: anneal/target - name: Install Anneal toolchain archive - run: cargo run setup --local-archive v2/target/anneal-exocrate.tar.zst - working-directory: anneal + run: cargo run setup --local-archive ../target/anneal-exocrate.tar.zst + working-directory: anneal/v1 - name: Verify example env: @@ -253,7 +253,7 @@ jobs: exit 1 fi fi - working-directory: anneal + working-directory: anneal/v1 # Build the Nix-produced toolchain archive once and fan out the exact archive # as a workflow artifact. This avoids forcing every downstream matrix runner @@ -283,8 +283,8 @@ jobs: id: restore_anneal_main_nix_cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - path: anneal/v2/target/nix-cache-main - key: anneal-v2-main-nix-cache-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('anneal/v2/flake.nix', 'anneal/v2/flake.lock', 'anneal/v2/rewrite-lake-vendor.py', 'anneal/v2/prune-lake-cache.py') }} + path: anneal/target/nix-cache-main + key: anneal-v2-main-nix-cache-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('anneal/flake.nix', 'anneal/flake.lock', 'anneal/rewrite-lake-vendor.py', 'anneal/prune-lake-cache.py') }} # Pull request caches are scoped by GitHub to the PR merge ref, so they # can speed up repeated pushes to the same PR without becoming visible to @@ -295,8 +295,8 @@ jobs: if: github.event_name == 'pull_request' uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - path: anneal/v2/target/nix-cache-pr - key: anneal-v2-pr-nix-cache-v1-${{ runner.os }}-${{ runner.arch }}-pr-${{ github.event.pull_request.number }}-${{ hashFiles('anneal/v2/flake.nix', 'anneal/v2/flake.lock', 'anneal/v2/rewrite-lake-vendor.py', 'anneal/v2/prune-lake-cache.py') }} + path: anneal/target/nix-cache-pr + key: anneal-v2-pr-nix-cache-v1-${{ runner.os }}-${{ runner.arch }}-pr-${{ github.event.pull_request.number }}-${{ hashFiles('anneal/flake.nix', 'anneal/flake.lock', 'anneal/rewrite-lake-vendor.py', 'anneal/prune-lake-cache.py') }} - name: Install Nix uses: DeterminateSystems/determinate-nix-action@d96678350ffd6a456235832eb11e1c491589b7bb # v3.21.8 @@ -336,7 +336,7 @@ jobs: exit 1 fi nix build "${nix_args[@]}" .#omnibus-archive-layout-check --no-link - working-directory: anneal/v2 + working-directory: anneal # Re-enable the AppArmor namespace restriction to restore the runner host's default security posture. # `if: always()` ensures this cleanup step runs even if the Nix build fails. @@ -358,13 +358,13 @@ jobs: # wrapper cheap; higher levels add CPU time for negligible size wins. nix copy .#omnibus-archive-ci \ --to "file://$PWD/target/nix-cache-main/?compression=zstd&compression-level=1&trusted=1" - working-directory: anneal/v2 + working-directory: anneal - name: Save Anneal Nix binary cache if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.restore_anneal_main_nix_cache.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - path: anneal/v2/target/nix-cache-main + path: anneal/target/nix-cache-main key: ${{ steps.restore_anneal_main_nix_cache.outputs.cache-primary-key }} - name: Populate Anneal PR Nix binary cache @@ -376,20 +376,20 @@ jobs: # archive itself uses zstd level 6; keep this wrapper at level 1. nix copy .#omnibus-archive-ci \ --to "file://$PWD/target/nix-cache-pr/?compression=zstd&compression-level=1&trusted=1" - working-directory: anneal/v2 + working-directory: anneal - name: Save Anneal PR Nix binary cache if: github.event_name == 'pull_request' && steps.restore_anneal_pr_nix_cache.outputs.cache-hit != 'true' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - path: anneal/v2/target/nix-cache-pr + path: anneal/target/nix-cache-pr key: ${{ steps.restore_anneal_pr_nix_cache.outputs.cache-primary-key }} - name: Upload Anneal toolchain archive uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: anneal-exocrate.tar.zst - path: anneal/v2/target/anneal-exocrate.tar.zst + path: anneal/target/anneal-exocrate.tar.zst if-no-files-found: error retention-days: 1 compression-level: 0 @@ -412,10 +412,10 @@ jobs: uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: anneal-exocrate.tar.zst - path: anneal/v2/target + path: anneal/target # FIXME: Pin this nightly to the same Rust date encoded in - # anneal/v2/flake.nix, or derive it from the archive metadata, so v2 CI is + # anneal/flake.nix, or derive it from the archive metadata, so v2 CI is # reproducible instead of following whatever nightly happens to be latest. - name: Install latest nightly Rust uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # zizmor: ignore[superfluous-actions] @@ -424,7 +424,7 @@ jobs: - name: Run V2 tests run: cargo test --workspace --all-features # include, e.g., tests that assume exocrate prebuilt - working-directory: anneal/v2 + working-directory: anneal # Used to signal to branch protections that all other jobs have succeeded. all-jobs-succeed: diff --git a/.vscode/settings.json b/.vscode/settings.json index ed16c0a374..37e5bf41f8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,7 +11,7 @@ "zerocopy/Cargo.toml", "tools/Cargo.toml", "anneal/Cargo.toml", - "anneal/v2/Cargo.toml", + "anneal/v1/Cargo.toml", "exocrate/Cargo.toml" ], // Extra cfgs added to rust-analyzer. diff --git a/anneal/Cargo.lock b/anneal/Cargo.lock index 04bcfa1bdb..cd9c673ac1 100644 --- a/anneal/Cargo.lock +++ b/anneal/Cargo.lock @@ -17,6 +17,18 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -28,14 +40,30 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.11.5" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" dependencies = [ "anstyle", + "memchr", "unicode-width 0.2.2", ] +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse 0.2.7", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstream" version = "1.0.0" @@ -43,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse", + "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -57,6 +85,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + [[package]] name = "anstyle-parse" version = "1.0.0" @@ -92,11 +129,26 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "ar_archive_writer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +dependencies = [ + "object", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "assert_cmd" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a686bbee5efb88a82df0621b236e74d925f470e5445d3220a5648b892ec99c9" +checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ "anstyle", "bstr", @@ -107,11 +159,20 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "backtrace" @@ -143,26 +204,11 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - [[package]] name = "bitflags" -version = "2.11.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" [[package]] name = "block-buffer" @@ -173,6 +219,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "brownstone" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5839ee4f953e811bfdcf223f509cb2c6a3e1447959b0bff459405575bc17f22" +dependencies = [ + "arrayvec", +] + [[package]] name = "bstr" version = "1.12.1" @@ -186,9 +241,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -207,16 +268,13 @@ dependencies = [ [[package]] name = "cargo-anneal" -version = "0.1.0-alpha.24" +version = "0.1.0-alpha.22" dependencies = [ "anyhow", - "assert_cmd", - "cargo_metadata 0.23.1", + "cargo_metadata", + "charon", "clap", "clap-cargo", - "console", - "dashmap", - "datatest-stable", "env_logger", "exocrate", "fs2", @@ -224,57 +282,26 @@ dependencies = [ "log", "miette", "pathdiff", - "predicates", - "proc-macro2", - "quote", "rayon", - "regex", "serde", "serde_json", "sha2", - "similar", - "strip-ansi-escapes", - "syn", "tempfile", - "thiserror 2.0.18", - "toml", - "ui_test", + "thiserror", + "toml_const", "walkdir", ] [[package]] name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" dependencies = [ "serde", "serde_core", ] -[[package]] -name = "cargo_metadata" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" -dependencies = [ - "camino", - "cargo-platform 0.1.9", - "semver", - "serde", - "serde_json", - "thiserror 1.0.69", -] - [[package]] name = "cargo_metadata" version = "0.23.1" @@ -282,18 +309,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ "camino", - "cargo-platform 0.3.2", + "cargo-platform", "semver", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror", ] [[package]] name = "cc" -version = "1.2.59" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", @@ -307,11 +334,62 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "charon" +version = "0.1.210" +source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" +dependencies = [ + "annotate-snippets", + "anstream 0.6.21", + "anyhow", + "assert_cmd", + "clap", + "colored", + "convert_case", + "derive_generic_visitor", + "either", + "env_logger", + "extension-traits", + "fraction", + "hashbrown 0.15.5", + "hax-adt-into", + "index_vec", + "indexmap", + "indoc", + "itertools", + "lazy_static", + "log", + "macros", + "nom", + "nom-supreme", + "num-bigint", + "paste", + "petgraph", + "postcard", + "rustc-hash", + "rustc_version", + "serde", + "serde_json", + "serde_stacker", + "serde_state", + "smallvec", + "stacker", + "strip-ansi-escapes", + "take_mut", + "tempfile", + "toml 0.8.23", + "tracing", + "tracing-subscriber", + "tracing-tree", + "ustr", + "which", +] + [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -324,7 +402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936551935c8258754bb8216aec040957d261f977303754b9bf1a213518388006" dependencies = [ "anstyle", - "cargo_metadata 0.23.1", + "cargo_metadata", "clap", "serde", "serde_json", @@ -336,7 +414,7 @@ version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream", + "anstream 1.0.0", "anstyle", "clap_lex", "strsim", @@ -344,14 +422,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -361,30 +439,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] -name = "color-eyre" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] - -[[package]] -name = "color-spantrace" +name = "cobs" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", + "thiserror", ] [[package]] @@ -395,19 +455,14 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" -version = "3.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ - "windows-sys 0.61.2", + "lazy_static", + "windows-sys 0.59.0", ] -[[package]] -name = "comma" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" - [[package]] name = "console" version = "0.16.3" @@ -420,6 +475,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -439,13 +503,10 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.5.15" +name = "critical-section" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-deque" @@ -483,29 +544,70 @@ dependencies = [ ] [[package]] -name = "dashmap" -version = "6.1.0" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", + "darling_core", + "darling_macro", ] [[package]] -name = "datatest-stable" -version = "0.3.3" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a867d7322eb69cf3a68a5426387a25b45cb3b9c5ee41023ee6cea92e2afadd82" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ - "camino", - "fancy-regex", - "libtest-mimic", - "walkdir", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_generic_visitor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21588db07753dafe6460b13faad18bd7e46548ce91ee38f0bc0f7529b3864b82" +dependencies = [ + "derive_generic_visitor_macros", +] + +[[package]] +name = "derive_generic_visitor_macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3aed1890235ebcf844a24263ecc395c4e57a970f13bcc9948989f22aa051aa7" +dependencies = [ + "convert_case", + "darling", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -546,18 +648,22 @@ dependencies = [ ] [[package]] -name = "doc_gen" -version = "0.1.0" -dependencies = [ - "tree-sitter", - "tree-sitter-lean4", -] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] -name = "either" -version = "1.15.0" +name = "embedded-io" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encode_unicode" @@ -575,13 +681,19 @@ dependencies = [ "regex", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "env_logger" version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ - "anstream", + "anstream 1.0.0", "anstyle", "env_filter", "jiff", @@ -604,12 +716,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "escape8259" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" - [[package]] name = "exocrate" version = "0.1.0" @@ -626,41 +732,48 @@ dependencies = [ ] [[package]] -name = "eyre" -version = "0.6.12" +name = "ext-trait" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5" +dependencies = [ + "ext-trait-proc_macros", +] + +[[package]] +name = "ext-trait-proc_macros" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a" dependencies = [ - "indenter", - "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "fancy-regex" -version = "0.14.0" +name = "extension-traits" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537" dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", + "ext-trait", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "filetime" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", ] [[package]] @@ -669,6 +782,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.9" @@ -680,13 +799,10 @@ dependencies = [ ] [[package]] -name = "float-cmp" -version = "0.10.0" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" -dependencies = [ - "num-traits", -] +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" @@ -694,6 +810,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "fraction" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "fs2" version = "0.4.3" @@ -704,6 +830,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -757,10 +907,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] -name = "hashbrown" -version = "0.14.5" +name = "hash32" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] [[package]] name = "hashbrown" @@ -773,9 +926,35 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "hax-adt-into" +version = "0.3.5" +source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", + "tracing", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] [[package]] name = "heck" @@ -785,9 +964,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", "itoa", @@ -806,19 +985,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] -name = "indenter" -version = "0.3.4" +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indent_write" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" + +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" +dependencies = [ + "serde", +] [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -837,6 +1031,15 @@ dependencies = [ "web-time", ] +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + [[package]] name = "is_ci" version = "1.2.0" @@ -849,6 +1052,15 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -857,9 +1069,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.23" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" dependencies = [ "jiff-static", "log", @@ -870,13 +1082,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.23" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -889,12 +1101,20 @@ dependencies = [ "libc", ] +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -911,40 +1131,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" -[[package]] -name = "levenshtein" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" - [[package]] name = "libc" -version = "0.2.184" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags", "libc", - "plain", - "redox_syscall 0.7.3", -] - -[[package]] -name = "libtest-mimic" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ba06f0ade6e504aff834d7c34298e5155c6baca353cc6a4aaff2f9fd7f33" -dependencies = [ - "anstream", - "anstyle", - "clap", - "escape8259", ] [[package]] @@ -964,15 +1163,34 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" + +[[package]] +name = "macros" +version = "0.1.0" +source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "matchers" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "miette" @@ -1001,9 +1219,15 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1015,10 +1239,106 @@ dependencies = [ ] [[package]] -name = "normalize-line-endings" -version = "0.3.0" +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom-supreme" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd3ae6c901f1959588759ff51c95d24b491ecb9ff91aa9c2ef4acc5b1dcab27" +dependencies = [ + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] [[package]] name = "num-traits" @@ -1029,6 +1349,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.37.3" @@ -1062,6 +1391,16 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + [[package]] name = "parking_lot_core" version = "0.9.12" @@ -1070,11 +1409,17 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", "windows-link", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pathdiff" version = "0.2.3" @@ -1087,6 +1432,61 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1095,15 +1495,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "portable-atomic" @@ -1113,13 +1507,32 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless", + "serde", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "predicates" version = "3.1.4" @@ -1128,10 +1541,7 @@ checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "difflib", - "float-cmp", - "normalize-line-endings", "predicates-core", - "regex", ] [[package]] @@ -1142,21 +1552,12 @@ checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "prettydiff" -version = "0.9.0" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac17546d82912e64874e3d5b40681ce32eac4e5834344f51efcf689ff1550a65" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ - "owo-colors", + "predicates-core", + "termtree", ] [[package]] @@ -1166,7 +1567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -1178,6 +1579,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" +dependencies = [ + "ar_archive_writer", + "cc", +] + [[package]] name = "quote" version = "1.0.45" @@ -1201,9 +1612,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -1228,15 +1639,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_syscall" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" -dependencies = [ - "bitflags", -] - [[package]] name = "redox_users" version = "0.5.2" @@ -1245,7 +1647,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror", ] [[package]] @@ -1297,6 +1699,12 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc_version" version = "0.4.1" @@ -1306,18 +1714,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustfix" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" -dependencies = [ - "serde", - "serde_json", - "thiserror 1.0.69", - "tracing", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1333,9 +1729,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "log", "once_cell", @@ -1348,9 +1744,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "zeroize", ] @@ -1389,9 +1785,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -1424,16 +1820,15 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ - "indexmap", "itoa", "memchr", "serde", @@ -1450,6 +1845,45 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_stacker" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4936375d50c4be7eff22293a9344f8e46f323ed2b3c243e52f89138d9bb0f4a" +dependencies = [ + "serde", + "serde_core", + "stacker", +] + +[[package]] +name = "serde_state" +version = "1.0.0" +source = "git+https://github.com/Nadrieril/serde_state?branch=main#9bffbc1b28fd93533bbd3ca835385f29cb51888f" +dependencies = [ + "serde", + "serde_state_derive", +] + +[[package]] +name = "serde_state_derive" +version = "1.0.0" +source = "git+https://github.com/Nadrieril/serde_state?branch=main#9bffbc1b28fd93533bbd3ca835385f29cb51888f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1478,9 +1912,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simd-adler32" @@ -1489,10 +1923,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] -name = "similar" -version = "2.7.0" +name = "siphasher" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -1501,21 +1941,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "spanned" -version = "0.4.1" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4b0c055fde758f086eb4a6e73410247df8a3837fd606d2caeeaf72aa566d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "anyhow", - "bstr", - "color-eyre", + "lock_api", ] [[package]] -name = "streaming-iterator" -version = "0.1.9" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stacker" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.61.2", +] [[package]] name = "strip-ansi-escapes" @@ -1559,6 +2010,17 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -1570,6 +2032,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tar" version = "0.4.46" @@ -1620,33 +2088,13 @@ dependencies = [ "unicode-width 0.2.2", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1657,7 +2105,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1669,6 +2117,39 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "toml" version = "0.8.23" @@ -1676,11 +2157,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_edit", ] +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml_const" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389864cf501669b741746e9bc35e66c67f2b80266482ad04c452e2410433f205" +dependencies = [ + "phf", + "toml 0.9.12+spec-1.1.0", + "toml_const_macros", +] + +[[package]] +name = "toml_const_macros" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0f202adfb96027640ad9786a0657775414482cfd840c19e9957ada8cfbbfd" +dependencies = [ + "indexmap", + "proc-macro2", + "quote", + "syn 2.0.117", + "toml 0.9.12+spec-1.1.0", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -1690,6 +2210,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -1698,10 +2227,19 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", ] [[package]] @@ -1710,6 +2248,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -1717,9 +2261,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "tracing-core" version = "0.1.36" @@ -1731,13 +2287,14 @@ dependencies = [ ] [[package]] -name = "tracing-error" -version = "0.2.1" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "tracing", - "tracing-subscriber", + "log", + "once_cell", + "tracing-core", ] [[package]] @@ -1746,72 +2303,35 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] -name = "tree-sitter" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" -dependencies = [ - "cc", - "regex", - "regex-syntax", - "serde_json", - "streaming-iterator", - "tree-sitter-language", -] - -[[package]] -name = "tree-sitter-language" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" - -[[package]] -name = "tree-sitter-lean4" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d274c5b559d3a46a0d5d200fc0593fa3fda035304fa794d5d4a760fbf69c2a5e" +name = "tracing-tree" +version = "0.4.0" +source = "git+https://github.com/Nadrieril/tracing-tree#841286bfffd3c2200810244506cd127013dbeff9" dependencies = [ - "cc", - "tree-sitter", + "nu-ansi-term", + "time", + "tracing-core", + "tracing-log", + "tracing-subscriber", ] [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "ui_test" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada249620d81f010b9a1472b63a5077ac7c722dd0f4bacf6528b313d0b8c15d8" -dependencies = [ - "annotate-snippets", - "anyhow", - "bstr", - "cargo-platform 0.1.9", - "cargo_metadata 0.18.1", - "color-eyre", - "colored", - "comma", - "crossbeam-channel", - "indicatif", - "levenshtein", - "prettydiff", - "regex", - "rustc_version", - "rustfix", - "serde", - "serde_json", - "spanned", -] +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" @@ -1827,9 +2347,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -1890,6 +2410,19 @@ dependencies = [ "log", ] +[[package]] +name = "ustr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208" +dependencies = [ + "ahash", + "byteorder", + "lazy_static", + "parking_lot", + "serde", +] + [[package]] name = "utf8-zero" version = "0.8.1" @@ -1950,11 +2483,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -1963,14 +2496,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -1981,9 +2514,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1991,22 +2524,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -2057,13 +2590,25 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +dependencies = [ + "either", + "env_home", + "rustix", + "winsafe", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2110,6 +2655,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -2192,6 +2746,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -2201,6 +2767,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -2222,7 +2794,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -2238,7 +2810,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -2290,6 +2862,26 @@ dependencies = [ "rustix", ] +[[package]] +name = "zerocopy" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "zeroize" version = "1.8.2" diff --git a/anneal/Cargo.toml b/anneal/Cargo.toml index 6fa3ab88f5..6f5fb09509 100644 --- a/anneal/Cargo.toml +++ b/anneal/Cargo.toml @@ -1,10 +1,14 @@ [workspace] -members = [".", "tools/doc_gen"] +members = ["."] + +[features] +# Enables tests that assume a prebuilt exocrate archive. +exocrate_tests = [] [package] name = "cargo-anneal" edition = "2024" -version = "0.1.0-alpha.24" +version = "0.1.0-alpha.22" description = "Formally verify that your safety comments are correct." categories = [ "development-tools::cargo-plugins", @@ -24,89 +28,42 @@ exclude = [".*", "testdata"] # this crate; `cargo anneal setup` uses this metadata by default when callers # do not provide a local archive. [package.metadata.exocrate.linux.x86_64] -sha256 = "d3d7bbcdfd2645f10e3e64a85b3e848197033992337c969a45576a3d0ec517d9" -url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-linux-x86_64.tar.zst" +sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +url = "https://example.com/linux-x86_64.tar.zst" [package.metadata.exocrate.macos.x86_64] -sha256 = "1252f15262d11f49795c8ed182a8b47f2ae4e627d90babb2f10636349f686438" -url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-macos-x86_64.tar.zst" +sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +url = "https://example.com/macos-x86_64.tar.zst" [package.metadata.exocrate.linux.aarch64] -sha256 = "a9c496fcf21670b2306d02722b9afcf375149315e929d53b6a7585d4daa19710" -url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-linux-aarch64.tar.zst" +sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +url = "https://example.com/linux-aarch64.tar.zst" [package.metadata.exocrate.macos.aarch64] -sha256 = "b4e0a5b420eb441e37564c365f06c215f61a3b825fc3df37293da7c3010d2b81" -url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-macos-aarch64.tar.zst" +sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +url = "https://example.com/macos-aarch64.tar.zst" [dependencies] +exocrate = { path = "../exocrate" } +toml_const = "1.3.0" +clap = { version = "4.5", features = ["derive"] } +clap-cargo = { version = "0.18.3", features = ["cargo_metadata"] } +env_logger = "0.11" +log = "0.4" anyhow = "1.0.102" cargo_metadata = "0.23.1" -clap = { version = "4.6.0", features = ["derive"] } -clap-cargo = { version = "0.18.3", features = ["cargo_metadata"] } -dashmap = "6.1.0" -env_logger = "0.11.10" -log = "0.4.29" miette = { version = "7.6.0", features = ["derive", "fancy"] } -proc-macro2 = { version = "1.0.106", features = ["span-locations"] } -rayon = "1.11.0" -serde = { version = "1.0.228", features = ["derive"] } -serde_json = "1.0.149" -syn = { version = "2.0.117", features = [ - "full", - "visit", - "extra-traits", - "parsing", - "printing", -] } -quote = "1.0" thiserror = "2.0.18" -walkdir = "2.5.0" +serde_json = "1.0.149" +serde = { version = "1.0.228", features = ["derive"] } indicatif = { version = "0.18.4", features = ["improved_unicode"] } -console = "0.16.3" -exocrate = { path = "../exocrate" } -sha2 = "0.10" fs2 = "0.4" -pathdiff = "0.2.3" -toml = "0.8" -tempfile = "3.27.0" - -[build-dependencies] +walkdir = "2.5.0" sha2 = "0.10" -toml = "0.8" +tempfile = "3.27.0" +rayon = "1.11.0" +# `tag` is `main` branch HEAD on 2026-06-03. +charon_lib = { package = "charon", git = "https://github.com/AeneasVerif/charon.git", tag = "nightly-2026.06.03", default-features = false } [dev-dependencies] -syn = { version = "2.0.117", features = [ - "printing", - "full", - "visit", - "extra-traits", - "parsing", -] } -proc-macro2 = { version = "1.0.106", features = ["span-locations"] } -ui_test = "0.30.4" -assert_cmd = "2.2.0" - -predicates = "3.1.4" - -datatest-stable = "0.3.3" -serde = { version = "1.0", features = ["derive"] } -toml = "0.8" -regex = "1.0" -strip-ansi-escapes = "0.2.1" -similar = "2.7.0" - -[package.metadata.build_rs] - -# The commit hash of the Aeneas repository to use. -# -# FIXME: Add a CI step to verify that this commit exists and matches the -# toolchain version. -aeneas_rev = "42c0e90dacf486f7d3ed5b6cde3a9a81f04915a4" - -# The Lean toolchain version to use. This must match the version of Lean used -# by Aeneas in the `lean-toolchain` file in the commit above. -lean_toolchain = "leanprover/lean4:v4.30.0-rc2" -[[test]] -name = "integration" -harness = false +pathdiff = "0.2" diff --git a/anneal/LICENSE-APACHE b/anneal/LICENSE-APACHE deleted file mode 120000 index 965b606f33..0000000000 --- a/anneal/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE \ No newline at end of file diff --git a/anneal/LICENSE-BSD b/anneal/LICENSE-BSD deleted file mode 120000 index d37ba4277e..0000000000 --- a/anneal/LICENSE-BSD +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-BSD \ No newline at end of file diff --git a/anneal/LICENSE-MIT b/anneal/LICENSE-MIT deleted file mode 120000 index 76219eb72e..0000000000 --- a/anneal/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT \ No newline at end of file diff --git a/anneal/v2/chase-aeneas-versions.sh b/anneal/chase-aeneas-versions.sh similarity index 100% rename from anneal/v2/chase-aeneas-versions.sh rename to anneal/chase-aeneas-versions.sh diff --git a/anneal/v2/check-flake-eval.sh b/anneal/check-flake-eval.sh similarity index 98% rename from anneal/v2/check-flake-eval.sh rename to anneal/check-flake-eval.sh index 22d71f04dd..5deef6e2ae 100644 --- a/anneal/v2/check-flake-eval.sh +++ b/anneal/check-flake-eval.sh @@ -11,7 +11,7 @@ set -euo pipefail ROOT="$(git rev-parse --show-toplevel)" -FLAKE="$ROOT/anneal/v2" +FLAKE="$ROOT/anneal" systems=( aarch64-darwin diff --git a/anneal/v2/flake.lock b/anneal/flake.lock similarity index 100% rename from anneal/v2/flake.lock rename to anneal/flake.lock diff --git a/anneal/v2/flake.nix b/anneal/flake.nix similarity index 100% rename from anneal/v2/flake.nix rename to anneal/flake.nix diff --git a/anneal/v2/prune-lake-cache.py b/anneal/prune-lake-cache.py similarity index 100% rename from anneal/v2/prune-lake-cache.py rename to anneal/prune-lake-cache.py diff --git a/anneal/v2/rewrite-lake-vendor.py b/anneal/rewrite-lake-vendor.py similarity index 100% rename from anneal/v2/rewrite-lake-vendor.py rename to anneal/rewrite-lake-vendor.py diff --git a/anneal/src/main.rs b/anneal/src/main.rs index 3d363b977d..b947700606 100644 --- a/anneal/src/main.rs +++ b/anneal/src/main.rs @@ -1,21 +1,25 @@ -mod aeneas; -mod charon; -mod diagnostics; -mod errors; -mod generate; -mod parse; +// Copyright 2026 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use clap::Parser as _; + +#[allow(dead_code)] mod resolve; +#[allow(dead_code)] mod scanner; -mod validate; - +#[allow(dead_code)] mod setup; -mod ui_test_shim; +#[allow(dead_code)] mod util; -use clap::Parser; - -/// Anneal: A Literate Verification Toolchain -#[derive(Parser, Debug)] +/// Anneal +#[derive(clap::Parser, Debug)] #[command(name = "cargo-anneal", version, about, long_about = None)] struct Cli { #[command(subcommand)] @@ -24,46 +28,61 @@ struct Cli { #[derive(clap::Subcommand, Debug)] enum Commands { - /// Verify a crate - Verify(resolve::Args), /// Setup Anneal dependencies - Setup(resolve::SetupArgs), - /// Expand a crate's Lean output - Expand(ExpandArgs), - /// Generate Lean workspace and print paths without building - Generate(resolve::Args), - #[command(hide = true)] - ToolchainPath, + Setup(SetupArgs), } -#[derive(clap::ValueEnum, Clone, Debug, Default, PartialEq)] -pub enum EmitFormat { - #[default] - All, - Anneal, - Aeneas, +#[derive(clap::Parser, Debug)] +pub struct SetupArgs { + /// Path to a local dependency archive to use instead of downloading. + #[arg(long, value_name = "path-to-local-archive")] + pub local_archive: Option, } -#[derive(Parser, Debug)] -pub struct ExpandArgs { - #[command(flatten)] - pub resolve_args: resolve::Args, +exocrate::config! { + const CONFIG: Config = Config { + rel_dir_path: [".anneal", "toolchain"], + versioned_files: &["../Cargo.toml", "../Cargo.lock"], + }; +} - /// Which tool's generated Lean code to output - #[arg(long, default_value_t, value_enum)] - pub emit: EmitFormat, +exocrate::parse_remote_archive! { + const REMOTE: RemoteArchive = "Cargo.toml" [ + (linux, x86_64), + (macos, x86_64), + (linux, aarch64), + (macos, aarch64), + ]; } -fn main() -> anyhow::Result<()> { +fn setup_installation_dir(args: SetupArgs) -> std::path::PathBuf { + let location = if std::env::var("__ANNEAL_LOCAL_DEV").is_ok() { + exocrate::Location::LocalDev + } else { + exocrate::Location::UserGlobal + }; + let source = match args.local_archive { + Some(local_archive) => exocrate::Source::Local(local_archive), + None => exocrate::Source::Remote(REMOTE), + }; + + let (installation_dir, _) = CONFIG + .resolve_installation_dir_or_install(location, source) + // FIXME: Implement unified error reporting (e.g., via `anyhow`). + .expect("failed to resolve-or-install dependencies"); + installation_dir +} + +fn setup(args: SetupArgs) { + let installation_dir = setup_installation_dir(args); + log::info!("anneal toolchain is installed at {:?}", installation_dir); +} + +fn main() { // Suppressing timestamps removes a source of nondeterminism that is // difficult to work around in integration tests. env_logger::builder().format_timestamp(None).init(); - if std::env::var("ANNEAL_UI_TEST_MODE").is_ok() { - ui_test_shim::run(); - return Ok(()); - } - let mut args_iter = std::env::args_os().peekable(); let bin_name = args_iter.next().unwrap_or_else(|| "cargo-anneal".into()); // If we're being run as a cargo plugin, the second argument will be "anneal". @@ -73,112 +92,251 @@ fn main() -> anyhow::Result<()> { let args = Cli::parse_from(std::iter::once(bin_name).chain(args_iter)); match args.command { - Commands::Verify(resolve_args) => { - prepare_and_run(&resolve_args, |locked_roots, packages| { - aeneas::verify_lean_workspace(locked_roots, packages) - })?; + Commands::Setup(args) => setup(args), + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "exocrate_tests")] + mod exocrate_tests { + use std::{ + fs, io, + path::{Path, PathBuf}, + process::Command, + sync::OnceLock, + }; + + use serde_json::{Value, json}; + + const LOCAL_ARCHIVE: &str = "target/anneal-exocrate.tar.zst"; + static INSTALLATION_DIR: OnceLock = OnceLock::new(); + + #[test] + fn test_setup() { + install_local_archive(); } - Commands::Generate(resolve_args) => { - prepare_and_run(&resolve_args, |locked_roots, packages| { - aeneas::generate_lean_workspace(locked_roots, packages)?; - let lean_root = locked_roots.lean_root(); - let toolchain = setup::Toolchain::resolve()?; - println!("Lean workspace generated at: {}", lean_root.display()); - println!(); - println!("To manually build and experiment:"); - println!(" 1. cd {}", lean_root.display()); - println!( - " 2. LAKE_CACHE_DIR={} {} --keep-toolchain build", - toolchain.cache_dir().display(), - toolchain.lean_bin().join("lake").display() - ); - Ok(()) - })?; + + #[test] + fn test_archive_lake_cache_reuse() { + let installation_dir = install_local_archive(); + let temp = tempfile::Builder::new() + .prefix("anneal-v2-archive-cache-reuse-") + .tempdir() + .expect("failed to create archive cache reuse tempdir"); + assert_archive_lake_cache_reuse(&installation_dir, temp.path()) + .expect("archive Lake cache reuse test failed"); + } + + fn install_local_archive() -> PathBuf { + // ASSUMPTION: The CI dependency builder downloads the Nix-built + // archive artifact to this path before running v2 tests. + INSTALLATION_DIR + .get_or_init(|| { + super::super::setup_installation_dir(super::super::SetupArgs { + local_archive: Some(LOCAL_ARCHIVE.into()), + }) + }) + .clone() + } + + fn assert_archive_lake_cache_reuse( + toolchain_root: &Path, + temp_root: &Path, + ) -> Result<(), Box> { + let aeneas_root = toolchain_root.join("aeneas"); + let aeneas_lean = aeneas_root.join("backends/lean"); + let lean_root = toolchain_root.join("lean"); + let workspace = temp_root.join("generated-workspace"); + + assert_no_write_bits(&aeneas_root)?; + + fs::create_dir_all(workspace.join("generated"))?; + fs::copy(aeneas_lean.join("lean-toolchain"), workspace.join("lean-toolchain"))?; + fs::write(workspace.join("generated/Generated.lean"), "import Aeneas\n")?; + fs::write( + workspace.join("lakefile.lean"), + format!( + r#"import Lake +open Lake DSL + +require aeneas from "{}" + +package anneal_verification + +@[default_target] +lean_lib Generated where + srcDir := "generated" + roots := #[`Generated] +"#, + lake_string(&aeneas_lean) + ), + )?; + write_relative_archive_manifest(&workspace, &aeneas_lean)?; + + // The Nix archive must support fresh generated workspaces without + // reconfiguring packages or rebuilding read-only Lake artifacts. + run_lake_archive_command( + &workspace, + &lean_root, + &["--keep-toolchain", "--old", "build", "Generated"], + )?; + run_lake_archive_command( + &workspace, + &lean_root, + &["--keep-toolchain", "env", "lean", "--json", "generated/Generated.lean"], + )?; + + Ok(()) } - Commands::Setup(args) => { - setup::run_setup(setup::SetupArgs { local_archive: args.local_archive })?; + + fn assert_no_write_bits(root: &Path) -> Result<(), Box> { + let metadata = fs::symlink_metadata(root)?; + if metadata.file_type().is_symlink() { + return Ok(()); + } + if has_write_bits(&metadata.permissions()) { + panic!("archive path should be read-only: {}", root.display()); + } + if metadata.is_dir() { + for entry in fs::read_dir(root)? { + assert_no_write_bits(&entry?.path())?; + } + } + Ok(()) + } + + #[cfg(unix)] + fn has_write_bits(permissions: &fs::Permissions) -> bool { + use std::os::unix::fs::PermissionsExt as _; + permissions.mode() & 0o222 != 0 } - Commands::ToolchainPath => { - let toolchain = setup::Toolchain::resolve()?; - println!("{}", toolchain.bin_dir().display()); + + #[cfg(not(unix))] + fn has_write_bits(permissions: &fs::Permissions) -> bool { + !permissions.readonly() } - Commands::Expand(expand_args) => { - prepare_and_run(&expand_args.resolve_args, |locked_roots, packages| { - let lean_generated_root = locked_roots.lean_generated_root(); - - for artifact in packages { - if artifact.start_from.is_empty() { - continue; - } - - let slug = artifact.artifact_slug(); - let output_dir = lean_generated_root.join(&slug); - - let emit_all = expand_args.emit == EmitFormat::All; - let emit_anneal = emit_all || expand_args.emit == EmitFormat::Anneal; - let emit_aeneas = emit_all || expand_args.emit == EmitFormat::Aeneas; - - println!("=== Lean expansion for: {} ===", artifact.name.target_name); - - if emit_aeneas { - println!("--- Aeneas ---"); - // Read Aeneas outputs from disk - let types_path = output_dir.join("Types.lean"); - let types_ext_path = output_dir.join("TypesExternal.lean"); - let funs_path = output_dir.join("Funs.lean"); - let funs_ext_path = output_dir.join("FunsExternal.lean"); - - if types_path.exists() { - println!("{}", std::fs::read_to_string(&types_path)?); - } - if types_ext_path.exists() { - println!("{}", std::fs::read_to_string(&types_ext_path)?); - } - if funs_path.exists() { - println!("{}", std::fs::read_to_string(&funs_path)?); - } - if funs_ext_path.exists() { - println!("{}", std::fs::read_to_string(&funs_ext_path)?); - } - } - - if emit_anneal { - println!("--- Anneal ---"); - let generated = generate::generate_artifact(artifact); - println!("{}", generated.code); - } + + fn write_relative_archive_manifest( + workspace: &Path, + aeneas_lean: &Path, + ) -> Result<(), Box> { + let aeneas_lean = fs::canonicalize(aeneas_lean)?; + let workspace = fs::canonicalize(workspace)?; + let manifest_path = aeneas_lean.join("lake-manifest.json"); + let manifest: Value = serde_json::from_reader(fs::File::open(&manifest_path)?)?; + let aeneas_packages = + manifest.get("packages").and_then(Value::as_array).ok_or_else(|| { + invalid_data(format!( + "Aeneas Lake manifest {} is missing packages", + manifest_path.display() + )) + })?; + + let aeneas_dir = relative_manifest_string(&aeneas_lean, &workspace)?; + let mut packages = vec![json!({ + "type": "path", + "name": "aeneas", + "dir": aeneas_dir, + "inherited": false, + })]; + + for entry in aeneas_packages { + let mut entry = entry.as_object().cloned().ok_or_else(|| { + invalid_data("Aeneas Lake manifest package entry is not an object") + })?; + let package_type = entry.get("type").and_then(Value::as_str).ok_or_else(|| { + invalid_data("Aeneas Lake manifest package entry is missing type") + })?; + if package_type != "path" { + return Err(invalid_data(format!( + "Aeneas Lake manifest package entry is {package_type:?}, not a path dependency" + )) + .into()); } + let package_dir = entry.get("dir").and_then(Value::as_str).ok_or_else(|| { + invalid_data("Aeneas Lake manifest package entry is missing dir") + })?; + let package_dir = Path::new(package_dir); + let package_dir = if package_dir.is_absolute() { + package_dir.to_path_buf() + } else { + aeneas_lean.join(package_dir) + }; + let package_dir = fs::canonicalize(package_dir)?; + entry.insert( + "dir".to_string(), + json!(relative_manifest_string(&package_dir, &workspace)?), + ); + entry.insert("inherited".to_string(), json!(true)); + packages.push(Value::Object(entry)); + } - Ok(()) + let manifest = json!({ + "version": "1.2.0", + "packagesDir": ".lake/packages", + "packages": packages, + "name": "anneal_verification", + "lakeDir": ".lake", + "fixedToolchain": false, + }); + fs::write( + workspace.join("lake-manifest.json"), + format!("{}\n", serde_json::to_string_pretty(&manifest)?), + )?; + Ok(()) + } + + fn relative_manifest_string( + path: &Path, + base: &Path, + ) -> Result> { + let path = pathdiff::diff_paths(path, base).ok_or_else(|| { + invalid_data(format!( + "failed to compute relative path from {} to {}", + base.display(), + path.display() + )) })?; + Ok(path.to_string_lossy().into_owned()) } - } - Ok(()) -} + fn lake_string(path: &Path) -> String { + path.to_string_lossy().replace('\\', "\\\\").replace('"', "\\\"") + } -fn prepare_and_run(resolve_args: &resolve::Args, f: F) -> anyhow::Result> -where - F: FnOnce(&resolve::LockedRoots, &[scanner::AnnealArtifact]) -> anyhow::Result, -{ - let roots = resolve::resolve_roots(resolve_args)?; - - let packages = scanner::scan_workspace(&roots)?; - if packages.is_empty() { - log::warn!( - "No Anneal annotations (/// ```lean ...) found in the selected targets. Nothing to verify." - ); - return Ok(None); - } + fn run_lake_archive_command( + workspace: &Path, + lean_root: &Path, + args: &[&str], + ) -> Result<(), Box> { + let lean_bin = lean_root.join("bin"); + let mut cmd = Command::new(lean_bin.join("lake")); + cmd.args(args).current_dir(workspace).env_clear(); + + let lib_var = + if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" } else { "LD_LIBRARY_PATH" }; + cmd.env( + lib_var, + std::env::join_paths([lean_root.join("lib"), lean_root.join("lib/lean")])?, + ); - let locked_roots = roots.lock_run_root()?; - validate::validate_artifacts( - &packages, - resolve_args.allow_sorry, - resolve_args.unsound_allow_is_valid, - )?; - charon::run_charon(resolve_args, &locked_roots, &packages)?; - aeneas::run_aeneas(&locked_roots, &packages, resolve_args)?; + let output = cmd.output()?; + if !output.status.success() { + return Err(io::Error::other(format!( + "lake {:?} failed with status {}\nstdout:\n{}\nstderr:\n{}", + args, + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + )) + .into()); + } + Ok(()) + } - Ok(Some(f(&locked_roots, &packages)?)) + fn invalid_data(message: impl Into) -> io::Error { + io::Error::new(io::ErrorKind::InvalidData, message.into()) + } + } } diff --git a/anneal/src/resolve.rs b/anneal/src/resolve.rs index 9a44f65296..a87fa5cde0 100644 --- a/anneal/src/resolve.rs +++ b/anneal/src/resolve.rs @@ -1,13 +1,30 @@ -use std::{env, fs, path::PathBuf}; - -use anyhow::{Context, Result, anyhow}; -use cargo_metadata::{Metadata, MetadataCommand, Package, PackageName, Target, TargetKind}; -use clap::Parser; -use sha2::{Digest, Sha256}; - -use crate::util::DirLock; - -#[derive(Parser, Debug)] +// Copyright 2026 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! Cargo package and target resolution for Anneal. +//! +//! Cargo selectors can identify several compilation artifacts depending on +//! package layout: default selection may include libraries and binaries, +//! `--tests` can build test harnesses plus supporting targets, and a library +//! target can expose several crate types such as `rlib` and `cdylib`. +//! +//! This module resolves that selection into one explicit Anneal artifact per +//! package target and target kind. Downstream stages process those artifacts +//! independently, assigning each its own LLBC path and Charon configuration. +//! This prevents selected rustc units from sharing a `--dest-file`, avoids +//! collisions between workspace packages with the same Rust crate name, and +//! permits per-target Charon options such as `--start-from` and `--opaque`. + +use anyhow::Context as _; +use sha2::Digest as _; + +#[derive(clap::Parser, Debug)] pub struct Args { #[command(flatten)] pub manifest: clap_cargo::Manifest, @@ -18,60 +35,40 @@ pub struct Args { #[command(flatten)] pub features: clap_cargo::Features, - /// Verify the library target + /// Verify the library target. #[arg(long)] pub lib: bool, - /// Verify specific binary targets + /// Verify specific binary targets. #[arg(long)] pub bin: Vec, - /// Verify all binary targets + /// Verify all binary targets. #[arg(long)] pub bins: bool, - /// Verify specific example targets + /// Verify specific example targets. #[arg(long)] pub example: Vec, - /// Verify all example targets + /// Verify all example targets. #[arg(long)] pub examples: bool, - /// Verify specific test targets + /// Verify specific test targets. #[arg(long)] pub test: Vec, - /// Verify all test targets + /// Verify all test targets. #[arg(long)] pub tests: bool, - /// Allow `sorry` in proofs and inject `sorry` for missing proofs - #[arg(long)] - pub allow_sorry: bool, - - /// Allow use of `isValid` annotations + /// Permit Lean proof admissions (`sorry`, `admit`, or `sorryAx`). /// - /// `isValid` annotations are currently unsound. In particular, Rust does - /// not yet support annotating a field with `unsafe`, denoting that it - /// carries an invariant. Thus, `isValid` annotations are effectively - /// advisory – any code which does not have a Anneal annotation can modify - /// invariant-carrying fields without needing to use an `unsafe` block. - /// Without an `unsafe` block, Anneal has no way of knowing that an - /// operation needs to be analyzed for soundness. - /// - /// Once the `syn` parser supports parsing `unsafe` fields (which are - /// already supported in a nightly Rust feature), Anneal will require that - /// `isValid` is only used on `unsafe` fields. + /// Without this explicit opt-in, generated Lean treats warnings as errors + /// so every declaration which semantically depends on an admission fails. #[arg(long)] - pub unsound_allow_is_valid: bool, -} - -#[derive(Parser, Debug)] -pub struct SetupArgs { - /// Install dependencies from a locally built exocrate archive. - #[arg(long, value_name = "path-to-local-archive")] - pub local_archive: Option, + pub allow_sorry: bool, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -97,23 +94,21 @@ pub enum AnnealTargetKind { Test, } -// We map `cargo_metadata::TargetKind` to our own `AnnealTargetKind` to -// strictly validate supported target types and simplify downstream logic. -// While `cargo_metadata` is exhaustive, we only care about a subset of -// targets relevant to verification. - impl AnnealTargetKind { pub fn is_lib(&self) -> bool { use AnnealTargetKind::*; - matches!(self, Lib | RLib | ProcMacro | CDyLib | DyLib | StaticLib) + match self { + Lib | RLib | ProcMacro | CDyLib | DyLib | StaticLib => true, + Bin | Example | Test => false, + } } } -impl TryFrom<&TargetKind> for AnnealTargetKind { +impl std::convert::TryFrom<&cargo_metadata::TargetKind> for AnnealTargetKind { type Error = (); - fn try_from(kind: &TargetKind) -> Result { - use TargetKind::*; + fn try_from(kind: &cargo_metadata::TargetKind) -> anyhow::Result { + use cargo_metadata::TargetKind::*; match kind { Lib => Ok(Self::Lib), RLib => Ok(Self::RLib), @@ -132,8 +127,15 @@ impl TryFrom<&TargetKind> for AnnealTargetKind { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct AnnealTargetName { - pub package_name: PackageName, + /// The Cargo package that owns this artifact. + pub package_name: cargo_metadata::PackageName, + /// The Cargo target name. pub target_name: String, + /// The target kind compiled for this artifact. + /// + /// This is part of the identity because one Cargo target can expose + /// multiple crate types, and because later Charon and Lean outputs must not + /// rely on target names alone. pub kind: AnnealTargetKind, } @@ -147,34 +149,32 @@ pub struct AnnealTargetName { pub struct AnnealTarget { pub name: AnnealTargetName, pub kind: AnnealTargetKind, - /// Path to the main source file for this target. - pub src_path: PathBuf, + /// Path to the `Cargo.toml` for this target. - pub manifest_path: PathBuf, + pub manifest_path: std::path::PathBuf, } #[derive(Debug)] pub struct Roots { - pub workspace: PathBuf, // E.g., `target/anneal`. - anneal_global_root: PathBuf, + anneal_global_root: std::path::PathBuf, // E.g., `target/anneal/`. - anneal_run_root: PathBuf, + anneal_run_root: std::path::PathBuf, pub roots: Vec, } impl Roots { - pub fn lock_run_root(&self) -> Result> { - let lock = DirLock::lock_exclusive(self.anneal_run_root.clone())?; - Ok(LockedRoots { roots: self, anneal_run_root: lock }) + pub fn lock_run_root(&self) -> anyhow::Result> { + let lock = crate::util::DirLock::lock_exclusive(self.anneal_run_root.clone())?; + Ok(LockedRoots { roots: self, anneal_run_root: lock, llbc_override: None }) } - pub fn cargo_target_dir(&self) -> PathBuf { + pub fn cargo_target_dir(&self) -> std::path::PathBuf { self.anneal_global_root.join("cargo_target") } } -/// A wrapper around `Roots` that proves the build lock is held. +/// A wrapper around [`crate::resolve::Roots`] that proves the build lock is held. /// /// This struct is the *only* way to access paths within the Anneal build /// directory (e.g., LLBC output, Lean generation). This enforces that all @@ -182,38 +182,37 @@ impl Roots { pub struct LockedRoots<'a> { roots: &'a Roots, anneal_run_root: crate::util::DirLock, + pub llbc_override: Option, } impl<'a> LockedRoots<'a> { - pub fn llbc_root(&self) -> PathBuf { - self.anneal_run_root.path.join("llbc") - } - - pub fn lean_root(&self) -> PathBuf { - self.anneal_run_root.path.join("lean") - } - - pub fn lean_generated_root(&self) -> PathBuf { - self.lean_root().join("generated") + pub fn llbc_root(&self) -> std::path::PathBuf { + if let Some(ref over) = self.llbc_override { + over.clone() + } else { + self.anneal_run_root.path.join("llbc") + } } // We expose the Cargo target directory for convenience, as it is used // by downstream tools like Charon to coordinate dependency artifacts. - pub fn cargo_target_dir(&self) -> PathBuf { + pub fn cargo_target_dir(&self) -> std::path::PathBuf { self.roots.cargo_target_dir() } - - pub fn workspace(&self) -> &PathBuf { - &self.roots.workspace - } } /// Resolves all verification roots. /// /// Each entry represents a distinct compilation artifact to be verified. -pub fn resolve_roots(args: &Args) -> Result { +/// Keeping this artifact list explicit is deliberate: later Charon invocation +/// code should not have to rediscover which files a Cargo flag happened to +/// produce for a particular workspace shape. +pub fn resolve_roots(args: &Args, toolchain: &crate::setup::Toolchain) -> anyhow::Result { log::trace!("resolve_roots({:?})", args); - let mut cmd = MetadataCommand::new(); + let mut cmd = cargo_metadata::MetadataCommand::new(); + cmd.cargo_path(crate::setup::Tool::Cargo.path(toolchain)) + .env("RUSTC", crate::setup::Tool::Rustc.path(toolchain)) + .env(crate::setup::rust_library_path_env_var(), toolchain.rust_lib()); if let Some(path) = &args.manifest.manifest_path { cmd.manifest_path(path); @@ -228,18 +227,19 @@ pub fn resolve_roots(args: &Args) -> Result { args.features.forward_metadata(&mut cmd); let metadata = cmd.exec().context("Failed to run 'cargo metadata'")?; + // We enforce that all local dependencies are contained within the workspace + // root. This is a temporary limitation to simplify the verification model + // and ensure a "hermetic-like" boundary for analysis. It prevents issues + // where experimental or local forks of dependencies might be picked up + // unpredictably, or where Charon might struggle to locate source files + // outside the standard project structure. + check_for_external_deps(&metadata)?; + let selected_packages = resolve_packages(&metadata, &args.workspace, args.manifest.manifest_path.as_deref())?; - check_selected_packages_in_workspace(&metadata, &selected_packages)?; let (anneal_global_root, anneal_run_root) = resolve_run_roots(&metadata); - let mut roots = Roots { - workspace: metadata.workspace_root.as_std_path().to_owned(), - // cargo_target_dir: metadata.target_directory.as_std_path().to_owned(), - anneal_global_root, - anneal_run_root, - roots: Vec::new(), - }; + let mut roots = Roots { anneal_global_root, anneal_run_root, roots: Vec::new() }; for package in selected_packages { log::trace!("Scanning package: {}", package.name); @@ -262,7 +262,6 @@ pub fn resolve_roots(args: &Args) -> Result { // reference for the rest of the pipeline. This avoids ambiguity // if the CWD changes or if we're working with complex workspace // structures. - src_path: target.src_path.as_std_path().to_owned(), manifest_path: package.manifest_path.as_std_path().to_owned(), })); } @@ -270,26 +269,22 @@ pub fn resolve_roots(args: &Args) -> Result { Ok(roots) } -fn resolve_run_roots(metadata: &Metadata) -> (PathBuf, PathBuf) { +fn resolve_run_roots( + metadata: &cargo_metadata::Metadata, +) -> (std::path::PathBuf, std::path::PathBuf) { log::trace!("resolve_run_root"); log::debug!("workspace_root: {:?}", metadata.workspace_root.as_std_path()); // NOTE: Automatically handles `CARGO_TARGET_DIR` env var. let target_dir = metadata.target_directory.as_std_path(); let anneal_global = target_dir.join("anneal"); - // Used by integration tests to ensure deterministic shadow dir names. - if let Ok(name) = std::env::var("ANNEAL_TEST_DIR_NAME") { - let run_root = anneal_global.join(name); - return (anneal_global, run_root); - } - // Hash the path to the workspace root to avoid collisions between different // workspaces using the same target directory. We use SHA-256 (truncated to // 64 bits) for stable hashing across Rust versions. This ensures that the // build directory name remains consistent for the same workspace root, // avoiding unnecessary cache invalidation. let workspace_root_hash = { - let mut hasher = Sha256::new(); + let mut hasher = sha2::Sha256::new(); hasher.update(b"anneal_build_salt"); hasher.update(metadata.workspace_root.as_str().as_bytes()); let result = hasher.finalize(); @@ -304,13 +299,13 @@ fn resolve_run_roots(metadata: &Metadata) -> (PathBuf, PathBuf) { /// Resolves which packages to process based on workspace flags and CWD. fn resolve_packages<'a>( - metadata: &'a Metadata, + metadata: &'a cargo_metadata::Metadata, args: &clap_cargo::Workspace, manifest_path: Option<&std::path::Path>, -) -> Result> { +) -> anyhow::Result> { log::trace!("resolve_packages(workspace: {}, all: {})", args.workspace, args.all); let mut packages = if !args.package.is_empty() { - // Resolve explicitly selected packages (-p / --package) + // Resolve explicitly selected packages (-p / --package). args.package .iter() .map(|name| { @@ -318,9 +313,9 @@ fn resolve_packages<'a>( .packages .iter() .find(|p| p.name == *name) - .ok_or_else(|| anyhow!("Package '{}' not found in workspace", name)) + .ok_or_else(|| anyhow::anyhow!("Package '{}' not found in workspace", name)) }) - .collect::>>()? + .collect::>>()? } else if args.workspace || args.all { // Resolve entire workspace (--workspace / --all). This explicitly // selects all workspace members, ignoring any packages that might be @@ -337,7 +332,7 @@ fn resolve_packages<'a>( let cwd = { let cwd_candidate = manifest_path .map(|p| p.to_path_buf()) - .unwrap_or_else(|| env::current_dir().unwrap_or_default()) + .unwrap_or_else(|| std::env::current_dir().unwrap_or_default()) .canonicalize() .context("Failed to canonicalize CWD")?; @@ -350,7 +345,7 @@ fn resolve_packages<'a>( } }; - // Find the package whose manifest directory is an ancestor of CWD + // Find the package whose manifest directory is an ancestor of CWD. let current_pkg = metadata.packages.iter().find(|p| { let manifest_dir = p.manifest_path.parent().unwrap(); cwd.starts_with(manifest_dir) @@ -368,14 +363,14 @@ fn resolve_packages<'a>( .filter_map(|id| metadata.packages.iter().find(|p| &p.id == id)) .collect() } else { - return Err(anyhow!( + return Err(anyhow::anyhow!( "Could not determine package from current directory. Please use -p or --workspace." )); } } }; - // Filter out excluded packages (--exclude) + // Filter out excluded packages (--exclude). if !args.exclude.is_empty() { packages.retain(|p| !args.exclude.contains(&p.name)); } @@ -383,8 +378,9 @@ fn resolve_packages<'a>( Ok(packages) } -/// Flattening Resolver: -/// Returns a list of (Target, TargetKind) pairs. +/// Resolves the Cargo targets selected from one package. +/// +/// Returns a list of `(Target, TargetKind)` pairs. /// If a target is defined as `crate-type = ["rlib", "cdylib"]`, and both are /// requested, this returns two entries, allowing them to be verified /// independently. @@ -392,12 +388,12 @@ fn resolve_packages<'a>( /// This flattening is critical because different crate types may be compiled /// with different flags or conditional compilation options (although the /// current scanner is CFG-agnostic, future improvements might respect this). -/// Verifying them independently ensures we cover all intended compilation -/// modes. +/// Verifying them independently gives later stages a separate artifact identity +/// and output path for every intended compilation mode. fn resolve_targets<'a>( - package: &'a Package, + package: &'a cargo_metadata::Package, args: &Args, -) -> Result> { +) -> anyhow::Result> { log::trace!("resolve_targets({})", package.name); let default_mode = !args.lib && args.bin.is_empty() @@ -439,38 +435,36 @@ fn resolve_targets<'a>( Ok(selected_artifacts) } -// TODO: Eventually, we'll want to support selected packages outside the Cargo -// workspace root by analyzing them in-place or teaching downstream stages how -// to map those source files. - -/// Ensures every selected verification root is contained within the workspace root. -fn check_selected_packages_in_workspace(metadata: &Metadata, packages: &[&Package]) -> Result<()> { - log::trace!("check_selected_packages_in_workspace"); - // Canonicalize workspace root to handle symlinks correctly - let workspace_root = fs::canonicalize(&metadata.workspace_root) +/// Scans the package graph to ensure all local dependencies are contained +/// within the workspace root. Returns an error if an external path dependency +/// is found. +pub fn check_for_external_deps(metadata: &cargo_metadata::Metadata) -> anyhow::Result<()> { + log::trace!("check_for_external_deps"); + // Canonicalize workspace root to handle symlinks correctly. + let workspace_root = std::fs::canonicalize(&metadata.workspace_root) .context("Failed to canonicalize workspace root")?; - for pkg in packages { - let pkg_path = pkg.manifest_path.as_std_path(); - - // Canonicalize the package path for comparison - let canonical_pkg_path = fs::canonicalize(pkg_path) - .with_context(|| format!("Failed to canonicalize path for package {}", pkg.name))?; - - // We only constrain the packages Anneal will scan as verification - // roots. Cargo metadata may also include build-only local path - // dependencies from the Anneal implementation itself, such as the - // repository-root `exocrate` helper crate when running - // `cargo run verify`. Rejecting those would make Anneal's own package - // layout constrain user verification. - if !canonical_pkg_path.starts_with(&workspace_root) { - anyhow::bail!( - "Unsupported external package: '{}' at {:?}.\n\ - Anneal currently only supports verifying packages contained \ - within the workspace root.", - pkg.name, - pkg_path - ); + for pkg in &metadata.packages { + // We only care about packages that are "local" (source is None). + // If source is Some(...), it's from crates.io or git, which is fine + // (handled by Cargo). + if pkg.source.is_none() { + let pkg_path = pkg.manifest_path.as_std_path(); + + // Canonicalize the package path for comparison. + let canonical_pkg_path = std::fs::canonicalize(pkg_path) + .with_context(|| format!("Failed to canonicalize path for package {}", pkg.name))?; + + // Check if the package lives outside the workspace tree. + if !canonical_pkg_path.starts_with(&workspace_root) { + anyhow::bail!( + "Unsupported external dependency: '{}' at {:?}.\n\ + Anneal currently only supports verifying workspaces where all local \ + dependencies are contained within the workspace root.", + pkg.name, + pkg_path + ); + } } } diff --git a/anneal/src/scanner.rs b/anneal/src/scanner.rs index 44b66417a8..7b4884c9ac 100644 --- a/anneal/src/scanner.rs +++ b/anneal/src/scanner.rs @@ -1,59 +1,51 @@ -use std::{ - collections::{HashMap, HashSet}, - ffi::OsStr, - path::{Path, PathBuf}, - sync::mpsc::{self, Sender}, -}; - -use anyhow::Result; -use sha2::{Digest as _, Sha256}; - -use crate::{ - parse::{self, ParsedLeanItem}, - resolve::{AnnealTargetKind, AnnealTargetName, LockedRoots, Roots}, -}; - -#[derive(Clone)] -struct ScannerContext { - err_tx: Sender, - // `ParsedLeanItem`s must have their `module_path` field updated to be - // relative to the crate root. - item_tx: Sender<(AnnealTargetName, ParsedLeanItem, String)>, - name: AnnealTargetName, - current_prefix: Vec, -} - -/// A scanned artifact containing all the necessary information to generate -/// a Lean specification. +// Copyright 2026 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use sha2::Digest as _; + +/// Represents a compilation target (artifact) that needs to be processed. /// -/// This represents a single Rust target (library, binary, etc.) and includes -/// the list of discovered Anneal items and the calculated entry points for -/// Charon. +/// Charon compiles the entire target to generate LLBC files. The generated +/// LLBC is the source of truth for processing Anneal annotations that affect +/// Aeneas code generation. +#[derive(Clone, Debug)] pub struct AnnealArtifact { - pub name: AnnealTargetName, - pub target_kind: AnnealTargetKind, + pub name: crate::resolve::AnnealTargetName, + pub target_kind: crate::resolve::AnnealTargetKind, /// The path to the crate's `Cargo.toml`. - pub manifest_path: PathBuf, - pub items: Vec>, - // NOTE: We store `start_from` as a `HashSet` rather than a `Vec` as an - // optimization: when we encounter items which we can't name (which carry - // Anneal annotations), we add their parent module to the list of - // entrypoints. If there are multiple items in the same module, this can - // lead to duplication in the list of entrypoints. Storing them in a - // `HashSet` avoids us having to de-dup later. - pub start_from: HashSet, + pub manifest_path: std::path::PathBuf, +} + +impl From<&crate::resolve::AnnealTarget> for AnnealArtifact { + fn from(target: &crate::resolve::AnnealTarget) -> Self { + Self { + name: target.name.clone(), + target_kind: target.kind, + manifest_path: target.manifest_path.clone(), + } + } } impl AnnealArtifact { - /// Returns a unique, Lean-compatible "slug" for this artifact that matches - /// the name that Aeneas will expect for the corresponding Lean module. + /// Returns a unique, Lean-compatible artifact slug. /// - /// Guarantees uniqueness based on manifest path even if multiple packages - /// have the same name. The slug is guaranteed to be a valid Lean - /// identifier (no hyphens). + /// Charon uses the slug as the file stem for the target's emitted LLBC + /// file. Later Aeneas/Lean stages can reuse the same Lean-compatible stem + /// when associating generated Lean code with this artifact. The slug is + /// guaranteed to be a valid Lean identifier (no hyphens), and is unique + /// based on the manifest path, target name, and target kind. pub fn artifact_slug(&self) -> String { fn hash(data: &[u8]) -> u64 { - let mut hasher = Sha256::new(); + // Use SHA-256 not for security but rather stability; Rust's + // `DefaultHasher` doesn't guarantee stability even across runs of + // the same binary. + let mut hasher = sha2::Sha256::new(); hasher.update(data); let result = hasher.finalize(); let mut bytes = [0u8; 8]; @@ -61,25 +53,11 @@ impl AnnealArtifact { u64::from_le_bytes(bytes) } - // Double-hash to make sure we can distinguish between e.g. - // (manifest_path, target_name) = ("abc", "def") and ("ab", "cdef"), - // which would hash identically if we just hashed their concatenation. - // - // Use SHA-256 not for security but rather stability – Rust's - // `DefaultHasher` doesn't guarantee stability even across runs of the - // same binary. - // - // `ANNEAL_HASH_WITH_REMOVED_PREFIX` allows our integration test - // framework to strip the randomized sandbox prefix from the manifest - // path before hashing, ensuring deterministic hashes even when running - // in a sandboxed environment. - let mut manifest_path_to_hash = self.manifest_path.as_path(); - if let Ok(prefix) = std::env::var("ANNEAL_HASH_WITH_REMOVED_PREFIX") { - if let Ok(stripped) = self.manifest_path.strip_prefix(&prefix) { - manifest_path_to_hash = stripped; - } - } - let h0 = hash(manifest_path_to_hash.as_os_str().as_encoded_bytes()); + // Compute `hash([hash(manifest_path), hash(target_name), hash(target_kind)])` to + // distinguish between e.g. (manifest_path, target_name) = ("abc", "def") and + // ("ab", "cdef"), which would hash identically if we just hashed their + // concatenation. + let h0 = hash(self.manifest_path.as_os_str().as_encoded_bytes()); let h1 = hash(self.name.target_name.as_bytes()); let h2 = hash(&[self.target_kind as u8]); let hashes = [h0, h1, h2]; @@ -104,7 +82,8 @@ impl AnnealArtifact { let pkg = to_pascal(self.name.package_name.as_str()); let target = to_pascal(&self.name.target_name); - // We use the hash to ensure uniqueness. + // We use the hash to ensure uniqueness even if our prior `to_pascal` + // mapping caused a collision. format!("{}{}{:08x}", pkg, target, h) } @@ -113,392 +92,11 @@ impl AnnealArtifact { format!("{}.llbc", self.artifact_slug()) } - /// Returns the name of the `.lean` spec file to use for this artifact. - pub fn lean_spec_file_name(&self) -> String { - format!("{}.lean", self.artifact_slug()) - } - /// Returns the absolute path to the .llbc file. /// - /// This method requires `LockedRoots` to ensure that the caller holds the + /// This method requires [`crate::resolve::LockedRoots`] to ensure that the caller holds the /// build lock before accessing the build artifact path. - pub fn llbc_path(&self, roots: &LockedRoots) -> PathBuf { + pub fn llbc_path(&self, roots: &crate::resolve::LockedRoots) -> std::path::PathBuf { roots.llbc_root().join(self.llbc_file_name()) } - - /// Returns true if this artifact contains items that should result in a `Funs.lean` file. - pub fn has_functions(&self) -> bool { - self.items.iter().any(|i| { - matches!( - i.item, - crate::parse::ParsedItem::Function(_) | crate::parse::ParsedItem::Impl(_) - ) - }) - } - - /// Returns true if this artifact contains items that should result in a `Types.lean` file. - pub fn has_types(&self) -> bool { - self.items.iter().any(|i| { - matches!(i.item, crate::parse::ParsedItem::Type(_) | crate::parse::ParsedItem::Trait(_)) - }) - } -} - -/// Scans the workspace to identify Anneal entry points (`/// ```lean` blocks) -/// and collects targets for verification. -pub fn scan_workspace(roots: &Roots) -> Result> { - log::trace!("scan_workspace({:?})", roots); - - let (err_tx, err_rx) = mpsc::channel::(); - let (item_tx, item_rx) = - mpsc::channel::<(AnnealTargetName, ParsedLeanItem, String)>(); - - let monitor_handle = std::thread::spawn(move || { - let mut error_count = 0; - for err in err_rx { - if error_count == 0 { - eprintln!("\n=== Anneal Verification Failed ==="); - } - error_count += 1; - // Use eprintln! to print immediately to stderr - // `miette::Report` natively formats with rich diagnostic spans via `{:?}`. - eprintln!("\n[Anneal Error] {:?}", err); - } - error_count - }); - - rayon::scope(|s| { - for target in &roots.roots { - let ctx = ScannerContext { - err_tx: err_tx.clone(), - item_tx: item_tx.clone(), - name: target.name.clone(), - current_prefix: vec!["crate".to_string()], - }; - s.spawn(move |s| { - process_file_recursive( - s, - &target.src_path, - ctx, - false, // Initial call is top-level, so not inside block - Vec::new(), - ) - }); - } - }); - - // Inform the monitor thread that no more errors will be sent, causing it to - // exit. - drop(err_tx); - - let (mut entry_points, mut start_from_map) = { - drop(item_tx); - let mut entry_points = - HashMap::>>::new(); - let mut start_from_map = HashMap::>::new(); - for (target, item, sf_str) in item_rx { - start_from_map.entry(target.clone()).or_default().insert(sf_str); - entry_points.entry(target).or_default().push(item); - } - (entry_points, start_from_map) - }; - - // Wait for the monitor to finish flushing the errors. - let count = monitor_handle.join().expect("Error monitor thread panicked"); - - if count > 0 { - return Err(anyhow::anyhow!("Aborting due to {} previous errors.", count)); - } - - Ok(roots - .roots - .iter() - .filter_map(|target| { - Some(AnnealArtifact { - name: target.name.clone(), - target_kind: target.kind, - manifest_path: target.manifest_path.clone(), - items: entry_points.remove(&target.name)?, - start_from: start_from_map.remove(&target.name).unwrap_or_default(), - }) - }) - .collect()) -} - -// NOTE: It might be tempting to try to deduplicate files to avoid re-processing -// a file that is reachable via multiple paths. However, this is incorrect, as -// this only happens if the file is named in multiple `#[path]` attributes, in -// which case it logically constitutes a distinct module each time it is -// referenced. -fn process_file_recursive<'a>( - scope: &rayon::Scope<'a>, - src_path: &Path, - ctx: ScannerContext, - inside_block: bool, - mut ancestors: Vec, -) { - log::trace!("process_file_recursive(src_path: {:?})", src_path); - - // Canonicalize the path to ensure we don't process the same file multiple - // times (e.g. via symlinks or different relative paths). - let src_path = match std::fs::canonicalize(src_path) { - Ok(p) => p, - Err(e) => { - // It is valid for a module to be declared but not exist (e.g., if - // it is cfg-gated for another platform). In strict Rust, we would - // check the cfg attributes, but since we are just scanning, it is - // safe to warn and return. - // - // Note: The scanner is currently CFG-agnostic. It does not evaluate - // `#[cfg(...)]` attributes, so it may attempt to scan files that - // are disabled for the current target (e.g., Windows-specific code - // on Linux). This is a known limitation that may cause build failures - // in Charon if it tries to verify non-existent items. - log::debug!("Skipping unreachable or missing file {:?}: {}", src_path, e); - return; - } - }; - - // Cycle detection: prevent infinite recursion on symlinks or recursive mod - // declarations, while still allowing identical files to be mounted in - // different branches of the tree. A cycle would represent an invalid crate - // anyway (i.e., an invalid set of `#[path]` attributes). - // - // Note: This check is purely path-based. It does not inspect the content of - // the file. - if ancestors.contains(&src_path) { - return; - } - ancestors.push(src_path.clone()); - - let result = parse::read_file_and_scan_compilation_unit( - &src_path, - inside_block, - |_src, res| match res { - Ok(mut item) => { - item.module_path.splice(0..0, ctx.current_prefix.clone()); - - let unreliable = match &item.item { - crate::parse::ParsedItem::Impl(_) => true, - crate::parse::ParsedItem::Function(f) => { - matches!( - f.item, - crate::parse::FunctionItem::Impl(..) - | crate::parse::FunctionItem::Trait(_) - | crate::parse::FunctionItem::Foreign(_) - ) - } - _ => false, - }; - let module_path = item.module_path.join("::"); - let start_from_str = if unreliable { - // For items where we cannot reliably determine the fully qualified - // name (e.g., items inside `impl` blocks or `trait` definitions), - // we must fall back to using the containing module as the - // entry point. This forces Charon to analyze the entire module, - // which is less efficient but ensures we don't miss the item. - module_path - } else { - format!("{}::{}", module_path, item.item.name().unwrap()) - }; - - use crate::parse::hkd::LiftToSafe; - // Before sending the parsed item across the thread boundary - // (from the `rayon` worker back to the main thread), we must - // "lift" the AST nodes. This internally drops the rich, - // non-`Send` `syn` trees stored in the `Local` mode, - // transforming them into the lightweight, `Send`-safe `Safe` - // equivalents (e.g., `SafeType` and `SafeSignature`). - ctx.item_tx.send((ctx.name.clone(), item.lift(), start_from_str)).unwrap(); - } - Err(e) => { - let _ = ctx.err_tx.send(miette::Report::new(e)); - } - }, - ); - - // After scanning the current file, we look for declared submodules that - // were not loaded inline (i.e., `mod foo;` instead of `mod foo { ... }`). - // `read_file_and_scan_compilation_unit` returns a list of these "unloaded" - // modules so we can resolve their paths and recurse. - let (_, unloaded_modules) = match result { - Ok(res) => res, - Err(e) => { - let _ = ctx.err_tx.send(miette::miette!("{:#}", e)); - return; - } - }; - - // Determine the directory to search for child modules in. - // - For `mod.rs`, `lib.rs`, `main.rs`, children are in the parent directory. - // e.g. `src/lib.rs` -> `mod foo` -> `src/foo.rs` - // - For `my_mod.rs`, children are in a sibling directory of the same name. - // e.g. `src/my_mod.rs` -> `mod sub` -> `src/my_mod/sub.rs` - let file_stem = src_path.file_stem().and_then(OsStr::to_str).unwrap_or(""); - let base_dir = if matches!(file_stem, "mod" | "lib" | "main") { - // If we are in `mod.rs`, `lib.rs`, or `main.rs`, then `mod foo;` - // looks for `foo.rs` or `foo/mod.rs` in the *same* directory. - // - // e.g. `src/lib.rs` -> `mod foo` -> `src/foo.rs` - src_path.parent().unwrap_or(&src_path).to_path_buf() - } else { - // If we are in `src/foo.rs`, then `mod bar;` looks for - // `src/foo/bar.rs` or `src/foo/bar/mod.rs`. - // - // e.g. src/foo.rs -> src/foo/ - src_path.with_extension("") - }; - - // Resolve and queue child modules for processing. - for module in unloaded_modules { - if let Some(mod_path) = - resolve_module_path(&base_dir, &module.name, module.path_attr.as_deref()) - { - // Spawn new tasks for discovered modules. - let mut ctx_clone = ctx.clone(); - ctx_clone.current_prefix.push(module.name); - - // TODO: Can we do something more efficient than cloning here? Maybe - // a linked list? - let ancestors = ancestors.clone(); - scope.spawn(move |s| { - process_file_recursive(s, &mod_path, ctx_clone, module.inside_block, ancestors) - }) - } else { - // This is an expected condition – it shows up when modules are - // conditionally compiled. Instead of implementing conditional - // compilation ourselves, we can just let rustc error later if - // this is actually an error. - // - // Example: `#[cfg(windows)] mod win_only;` on Linux. `win_only.rs` - // might not exist at all, or might verify successfully but be - // ignored by rustc. We just skip it here. - log::debug!("Could not resolve module '{}' in {:?}", module.name, src_path); - } - } -} - -/// Resolves a module name to a file path, checking standard Rust locations. -/// -/// * `base_dir`: The directory containing the parent file. -/// * `mod_name`: The name of the module (e.g., "foo"). -/// * `path_attr`: The optional `#[path = "..."]` attribute string. -fn resolve_module_path( - base_dir: &Path, - mod_name: &str, - path_attr: Option<&str>, -) -> Option { - log::trace!( - "resolve_module_path(base_dir: {:?}, mod_name: {:?}, path_attr: {:?})", - base_dir, - mod_name, - path_attr - ); - - // If `#[path = "..."]` is present, it overrides the standard lookup logic. - // The path is always relative to the current module's directory. - if let Some(custom_path) = path_attr { - let p = base_dir.join(custom_path); - if p.exists() { - return Some(p); - } - return None; - } - - // Standard lookup: `foo.rs` - let inline = base_dir.join(format!("{}.rs", mod_name)); - if inline.exists() { - return Some(inline); - } - - // Standard lookup: `foo/mod.rs` - let nested = base_dir.join(mod_name).join("mod.rs"); - if nested.exists() { - return Some(nested); - } - - None -} - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use cargo_metadata::PackageName; - - use super::*; - use crate::resolve::{AnnealTargetKind, AnnealTargetName}; - - #[test] - fn test_llbc_file_name_collision() { - let name_lib = AnnealTargetName { - package_name: PackageName::new("pkg".to_string()), - target_name: "name".to_string(), - kind: AnnealTargetKind::Lib, - }; - - let artifact_lib = AnnealArtifact { - name: name_lib.clone(), - target_kind: AnnealTargetKind::Lib, - manifest_path: PathBuf::from("Cargo.toml"), - start_from: std::collections::HashSet::new(), - items: vec![], - }; - - let name_bin = AnnealTargetName { - package_name: PackageName::new("pkg".to_string()), - target_name: "name".to_string(), - kind: AnnealTargetKind::Bin, - }; - - let artifact_bin = AnnealArtifact { - name: name_bin, - target_kind: AnnealTargetKind::Bin, - manifest_path: PathBuf::from("Cargo.toml"), - start_from: std::collections::HashSet::new(), - items: vec![], - }; - - let artifact_workspace_collision = AnnealArtifact { - name: name_lib.clone(), - target_kind: AnnealTargetKind::Lib, - // A different manifest but identical package/target semantics - manifest_path: PathBuf::from("crates/other/Cargo.toml"), - start_from: std::collections::HashSet::new(), - items: vec![], - }; - - // The file names must be distinct because of the trailing hash. - assert_ne!(artifact_lib.llbc_file_name(), artifact_bin.llbc_file_name()); - assert!(artifact_lib.llbc_file_name().starts_with("PkgName")); - assert!(artifact_bin.llbc_file_name().starts_with("PkgName")); - - // Distinct `manifest_path`s must prevent collisions even when the - // package name and target semantics are otherwise identical. - assert_ne!(artifact_lib.llbc_file_name(), artifact_workspace_collision.llbc_file_name()); - assert!(artifact_workspace_collision.llbc_file_name().starts_with("PkgName")); - } - - #[test] - fn test_lean_spec_file_name_uses_slug() { - let name = AnnealTargetName { - package_name: PackageName::new("pkg-foo".to_string()), - target_name: "name-bar".to_string(), - kind: AnnealTargetKind::Lib, - }; - - let artifact = AnnealArtifact { - name, - target_kind: AnnealTargetKind::Lib, - manifest_path: PathBuf::from("Cargo.toml"), - start_from: std::collections::HashSet::new(), - items: vec![], - }; - - // Slug should be PascalCase: PkgFoo_NameBar_ - // Spec file should be slug + .lean - let spec_name = artifact.lean_spec_file_name(); - assert!(spec_name.starts_with("PkgFooNameBar")); - assert!(spec_name.ends_with(".lean")); - } } diff --git a/anneal/src/setup.rs b/anneal/src/setup.rs index b6d25ade59..9e17911f4d 100644 --- a/anneal/src/setup.rs +++ b/anneal/src/setup.rs @@ -1,213 +1,154 @@ -//! Subcommand for installing Anneal dependencies. - -use std::{path::PathBuf, process::Command}; +// Copyright 2026 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. use anyhow::Context as _; pub struct SetupArgs { - pub local_archive: Option, + pub local_archive: Option, } -pub const CONFIG: exocrate::Config = exocrate::Config { - rel_dir_path: &["anneal", "toolchain"], - version_slug: env!("ANNEAL_EXOCRATE_VERSION_SLUG"), -}; +exocrate::config! { + pub const CONFIG: Config = Config { + rel_dir_path: [".anneal", "toolchain"], + versioned_files: &["../Cargo.toml", "../Cargo.lock"], + }; +} + +exocrate::parse_remote_archive! { + pub const REMOTE: RemoteArchive = "Cargo.toml" [ + (linux, x86_64), + (macos, x86_64), + (linux, aarch64), + (macos, aarch64), + ]; +} -#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Tool { + Cargo, Charon, - #[allow(dead_code)] - CharonDriver, - Aeneas, + Rustc, } impl Tool { pub fn name(&self) -> &'static str { match self { + Self::Cargo => "cargo", Self::Charon => "charon", - Self::CharonDriver => "charon-driver", - Self::Aeneas => "aeneas", + Self::Rustc => "rustc", } } - pub fn path(&self, toolchain: &Toolchain) -> PathBuf { + pub fn path(&self, toolchain: &Toolchain) -> std::path::PathBuf { match self { - Self::Charon | Self::CharonDriver | Self::Aeneas => { - toolchain.aeneas_bin_dir().join(self.name()) - } + Self::Cargo | Self::Rustc => toolchain.rust_bin().join(self.name()), + Self::Charon => toolchain.aeneas_bin_dir().join(self.name()), } } } const AENEAS_DIR: &str = "aeneas"; -const AENEAS_BACKENDS_DIR: &str = "backends"; -const AENEAS_LEAN_DIR: &str = "lean"; -const BIN_DIR: &str = "bin"; -const LIB_DIR: &str = "lib"; -const LEAN_SYSROOT: &str = "lean"; const RUST_SYSROOT: &str = "rust"; +const AENEAS_BIN_DIR: &str = "bin"; +const RUST_BIN_DIR: &str = "bin"; +const RUST_LIB_DIR: &str = "lib"; pub struct Toolchain { - pub root: PathBuf, + root: std::path::PathBuf, } impl Toolchain { pub fn resolve() -> anyhow::Result { + let location = resolve_location(); let root = CONFIG - .resolve_installation_dir(location()) + .resolve_installation_dir(location) .context("Toolchain not installed. Please run 'cargo anneal setup' first.")?; Ok(Self { root }) } - pub fn bin_dir(&self) -> PathBuf { - self.aeneas_bin_dir() - } - - pub fn cache_dir(&self) -> PathBuf { - self.root.join("lake-cache") - } - - pub fn aeneas_root(&self) -> PathBuf { - self.root.join(AENEAS_DIR) + #[cfg(all(test, feature = "exocrate_tests"))] + pub fn root(&self) -> &std::path::Path { + &self.root } - pub fn aeneas_bin_dir(&self) -> PathBuf { - self.aeneas_root().join(BIN_DIR) + pub fn aeneas_bin_dir(&self) -> std::path::PathBuf { + self.root.join(AENEAS_DIR).join(AENEAS_BIN_DIR) } - pub fn aeneas_lean_dir(&self) -> PathBuf { - self.aeneas_root().join(AENEAS_BACKENDS_DIR).join(AENEAS_LEAN_DIR) - } - - pub fn rust_sysroot(&self) -> PathBuf { + pub fn rust_sysroot(&self) -> std::path::PathBuf { self.root.join(RUST_SYSROOT) } - pub fn rust_bin(&self) -> PathBuf { - self.rust_sysroot().join(BIN_DIR) + pub fn rust_bin(&self) -> std::path::PathBuf { + self.rust_sysroot().join(RUST_BIN_DIR) } - pub fn rust_lib(&self) -> PathBuf { - self.rust_sysroot().join(LIB_DIR) + pub fn rust_lib(&self) -> std::path::PathBuf { + self.rust_sysroot().join(RUST_LIB_DIR) } - pub fn lean_sysroot(&self) -> PathBuf { - self.root.join(LEAN_SYSROOT) + pub fn command(&self, tool: Tool) -> anyhow::Result { + let mut cmd = std::process::Command::new(tool.path(self)); + cmd.env_clear(); + match tool { + Tool::Cargo | Tool::Rustc => {} + Tool::Charon => { + // The archive supplies Rust tools, but not host build tools + // such as the linker. Keep the caller's `PATH` after our Rust + // bin directory so Cargo builds use the managed Rust toolchain + // while still finding those host tools. + cmd.env("CHARON_TOOLCHAIN_IS_IN_PATH", "1") + .env("PATH", prepend_current_path(self.rust_bin())?) + .env(rust_library_path_env_var(), self.rust_lib()); + } + } + Ok(cmd) } +} - pub fn lean_bin(&self) -> PathBuf { - self.lean_sysroot().join(BIN_DIR) +fn prepend_current_path(path: std::path::PathBuf) -> anyhow::Result { + let mut paths = vec![path]; + if let Some(current_path) = std::env::var_os("PATH") { + paths.extend(std::env::split_paths(¤t_path)); } + std::env::join_paths(paths).context("failed to construct PATH for tool command") +} - pub fn command(&self, tool: Tool) -> Command { - if std::env::var("ANNEAL_USE_PATH_FOR_TOOLS").is_ok() { - Command::new(tool.name()) - } else { - Command::new(tool.path(self)) - } - } +/// Returns the platform library search path variable used by Rust tools. +pub(crate) fn rust_library_path_env_var() -> &'static str { + if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" } else { "LD_LIBRARY_PATH" } } pub fn run_setup(args: SetupArgs) -> anyhow::Result<()> { - let local_archive = args - .local_archive - .or_else(|| std::env::var_os("ANNEAL_SETUP_LOCAL_ARCHIVE").map(PathBuf::from)); - let source = match local_archive { + let location = resolve_location(); + let source = match args.local_archive { Some(local_archive) => exocrate::Source::Local(local_archive), - None => exocrate::Source::Remote(remote_archive()), + None => exocrate::Source::Remote(REMOTE), }; - let installation_dir = CONFIG - .resolve_installation_dir_or_install(location(), source) + let (installation_dir, status) = CONFIG + .resolve_installation_dir_or_install(location, source) .context("failed to resolve-or-install dependencies")?; - log::info!("anneal toolchain is installed at {:?}", installation_dir); + match status { + exocrate::ResolvedOrInstalled::ResolvedExisting => { + log::warn!("anneal toolchain was already installed at {:?}", installation_dir); + } + exocrate::ResolvedOrInstalled::NewlyInstalled => { + log::info!("anneal toolchain freshly installed at {:?}", installation_dir); + } + } Ok(()) } -fn location() -> exocrate::Location { - if let Some(dir) = std::env::var_os("ANNEAL_TOOLCHAIN_DIR") { - exocrate::Location::Custom(PathBuf::from(dir)) - } else if std::env::var("__ZEROCOPY_LOCAL_DEV").is_ok() - || std::env::var("__ANNEAL_LOCAL_DEV").is_ok() - { +fn resolve_location() -> exocrate::Location { + if std::env::var("__ANNEAL_LOCAL_DEV").is_ok() { exocrate::Location::LocalDev } else { exocrate::Location::UserGlobal } } - -fn remote_archive() -> exocrate::RemoteArchive { - match (std::env::consts::OS, std::env::consts::ARCH) { - ("linux", "x86_64") => remote_archive_for( - env!("ANNEAL_EXOCRATE_LINUX_X86_64_URL"), - env!("ANNEAL_EXOCRATE_LINUX_X86_64_SHA256"), - ), - ("macos", "x86_64") => remote_archive_for( - env!("ANNEAL_EXOCRATE_MACOS_X86_64_URL"), - env!("ANNEAL_EXOCRATE_MACOS_X86_64_SHA256"), - ), - ("linux", "aarch64") => remote_archive_for( - env!("ANNEAL_EXOCRATE_LINUX_AARCH64_URL"), - env!("ANNEAL_EXOCRATE_LINUX_AARCH64_SHA256"), - ), - ("macos", "aarch64") => remote_archive_for( - env!("ANNEAL_EXOCRATE_MACOS_AARCH64_URL"), - env!("ANNEAL_EXOCRATE_MACOS_AARCH64_SHA256"), - ), - (os, arch) => panic!("unsupported platform: {os}-{arch}"), - } -} - -fn remote_archive_for(url: &'static str, sha256: &'static str) -> exocrate::RemoteArchive { - exocrate::RemoteArchive { - url, - sha256: decode_hex(sha256).expect("package.metadata.exocrate sha256 must be valid hex"), - } -} - -fn decode_hex(s: &str) -> Option<[u8; 32]> { - let bytes = s.as_bytes(); - if bytes.len() != 64 { - return None; - } - let mut res = [0u8; 32]; - for i in 0..32 { - let h_nib = decode_nibble(bytes[i * 2])?; - let l_nib = decode_nibble(bytes[i * 2 + 1])?; - res[i] = (h_nib << 4) | l_nib; - } - Some(res) -} - -fn decode_nibble(c: u8) -> Option { - match c { - b'0'..=b'9' => Some(c - b'0'), - b'a'..=b'f' => Some(c - b'a' + 10), - b'A'..=b'F' => Some(c - b'A' + 10), - _ => None, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn tool_paths_use_omnibus_layout() { - let toolchain = Toolchain { root: PathBuf::from("/tmp/toolchain") }; - - assert_eq!(toolchain.bin_dir(), PathBuf::from("/tmp/toolchain/aeneas/bin")); - assert_eq!( - toolchain.aeneas_lean_dir(), - PathBuf::from("/tmp/toolchain/aeneas/backends/lean") - ); - assert_eq!( - Tool::Charon.path(&toolchain), - PathBuf::from("/tmp/toolchain/aeneas/bin/charon") - ); - assert_eq!( - Tool::Aeneas.path(&toolchain), - PathBuf::from("/tmp/toolchain/aeneas/bin/aeneas") - ); - } -} diff --git a/anneal/src/util.rs b/anneal/src/util.rs index fe085b37dc..602e1585d1 100644 --- a/anneal/src/util.rs +++ b/anneal/src/util.rs @@ -1,16 +1,25 @@ -use std::path::PathBuf; +// Copyright 2026 The Fuchsia Authors +// +// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. -use anyhow::{Context, Result}; -use fs2::FileExt; +use std::io::BufRead as _; + +use anyhow::Context as _; +use fs2::FileExt as _; /// Represents an active, exclusive lock on a directory. /// /// This struct guarantees that the process holds an OS-level file lock /// guarding the specified directory. -pub struct DirLock { +pub(crate) struct DirLock { /// The path to the directory being guarded. - pub path: PathBuf, - // Kept alive to hold the flock + pub(crate) path: std::path::PathBuf, + // Kept alive to hold the flock. _file: std::fs::File, } @@ -22,17 +31,29 @@ impl DirLock { /// the directory itself to avoid platform-specific issues with /// directory locking and to ensure the lock file persists even if /// the directory is cleaned. - pub fn lock_exclusive(path: PathBuf) -> Result { + pub(crate) fn lock_exclusive(path: std::path::PathBuf) -> anyhow::Result { let file = Self::open_lock_file(&path)?; file.lock_exclusive() .with_context(|| format!("Failed to acquire exclusive lock on {:?}", path))?; Ok(Self { path, _file: file }) } - fn open_lock_file(path: &std::path::Path) -> Result { + /// Acquires a shared lock on the specified directory. + /// + /// Multiple processes can hold shared locks simultaneously, but an + /// exclusive lock will block until all shared locks are released. + #[cfg(any(test, feature = "exocrate_tests"))] + pub(crate) fn lock_shared(path: std::path::PathBuf) -> anyhow::Result { + let file = Self::open_lock_file(&path)?; + file.lock_shared() + .with_context(|| format!("Failed to acquire shared lock on {:?}", path))?; + Ok(Self { path, _file: file }) + } + + fn open_lock_file(path: &std::path::Path) -> anyhow::Result { let lock_path = path.join(".lock"); - // Ensure the directory exists + // Ensure the directory exists. if let Some(parent) = lock_path.parent() { std::fs::create_dir_all(parent).with_context(|| { format!("Failed to create directory for lock file: {:?}", parent) @@ -57,3 +78,206 @@ impl DirLock { } } } + +pub(crate) struct ProcessOutput { + pub status: std::process::ExitStatus, + pub stderr_lines: Vec, +} + +/// Spawns a child process, drains its stderr in a background thread, and processes +/// its stdout line-by-line in the main thread while showing a progress spinner. +pub(crate) fn run_command_with_progress( + mut cmd: std::process::Command, + pb: Option, + mut process_stdout_line: F, +) -> anyhow::Result +where + F: FnMut(&str, Option<&indicatif::ProgressBar>) -> anyhow::Result<()>, +{ + cmd.stdout(std::process::Stdio::piped()); + cmd.stderr(std::process::Stdio::piped()); + + let mut child = cmd.spawn().context("Failed to spawn child process")?; + + let stderr_buffer = std::sync::Arc::new(std::sync::Mutex::new(Vec::new())); + let stderr_buffer_clone = std::sync::Arc::clone(&stderr_buffer); + + let mut stderr_thread = None; + if let Some(stderr) = child.stderr.take() { + stderr_thread = Some(std::thread::spawn(move || { + let reader = std::io::BufReader::new(stderr); + for line in reader.lines().map_while(Result::ok) { + stderr_buffer_clone.lock().unwrap().push(line); + } + })); + } + + if let Some(ref p) = pb { + p.enable_steady_tick(std::time::Duration::from_millis(100)); + } + + if let Some(stdout) = child.stdout.take() { + let reader = std::io::BufReader::new(stdout); + for line in reader.lines().map_while(Result::ok) { + process_stdout_line(&line, pb.as_ref())?; + if let Some(ref p) = pb { + p.tick(); + } + } + } + + if let Some(ref p) = pb { + p.finish_and_clear(); + } + + let status = child.wait().context("Failed to wait for child process")?; + + if let Some(thread) = stderr_thread { + let _ = thread.join(); + } + + let stderr_lines = std::sync::Arc::try_unwrap(stderr_buffer).unwrap().into_inner().unwrap(); + + Ok(ProcessOutput { status, stderr_lines }) +} + +/// Performs a lock test action according to the `role` of the current actor. Actors may: +/// +/// - Obtain an exclusive or shared lock for `lock_dir`, +/// - Log actions in `log_file`, +/// - Wait for a signal from `sig_file`. +/// +/// Individual tests compose multiple role-based actions and verify the resulting action log. +#[cfg(feature = "exocrate_tests")] +pub(crate) fn run_test_lock_helper( + role: &str, + lock_dir: &std::path::Path, + log_file: &std::path::Path, + sig_file: &std::path::Path, +) -> anyhow::Result<()> { + use std::io::Write as _; + + let append_log = |msg: &str| -> anyhow::Result<()> { + let mut file = std::fs::OpenOptions::new().create(true).append(true).open(log_file)?; + writeln!(file, "{}", msg)?; + Ok(()) + }; + + let wait_for_sig = || -> anyhow::Result<()> { + let start = std::time::Instant::now(); + while !sig_file.exists() { + if start.elapsed() > std::time::Duration::from_secs(3) { + anyhow::bail!("Timeout waiting for signal file {:?}", sig_file); + } + std::thread::sleep(std::time::Duration::from_millis(50)); + } + Ok(()) + }; + + match role { + "reader-a" => { + let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; + append_log("SHARED_START_A")?; + wait_for_sig()?; + append_log("SHARED_END_A")?; + } + "reader-b" => { + let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; + append_log("SHARED_START_B")?; + std::fs::write(sig_file, "")?; + append_log("SHARED_END_B")?; + } + "writer-a" => { + let _lock = DirLock::lock_exclusive(lock_dir.to_path_buf())?; + append_log("EXCLUSIVE_START_A")?; + wait_for_sig()?; + append_log("EXCLUSIVE_END_A")?; + } + "reader-exclusion" => { + std::fs::write(sig_file, "")?; + let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; + append_log("SHARED_START_B")?; + append_log("SHARED_END_B")?; + } + _ => anyhow::bail!("Unknown test-lock-helper role: {}", role), + } + + Ok(()) +} + +#[cfg(test)] +#[macro_export] +macro_rules! workspace_fixture { + ($dir:expr, { $($path:expr => $content:expr),* $(,)? }) => {{ + let root = $dir.path(); + $( + let file_path = root.join($path); + if let Some(parent) = file_path.parent() { + std::fs::create_dir_all(parent).unwrap(); + } + std::fs::write(&file_path, $content).unwrap(); + )* + }}; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dir_lock_exclusive_mutual_exclusion() { + let temp_dir = tempfile::tempdir().unwrap(); + let lock_path = temp_dir.path().to_path_buf(); + + let barrier = std::sync::Arc::new(std::sync::Barrier::new(2)); + let barrier_clone = std::sync::Arc::clone(&barrier); + let lock_path_clone = lock_path.clone(); + + let lock_released = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let lock_released_clone = std::sync::Arc::clone(&lock_released); + + // Thread A acquires the lock. + let thread_a = std::thread::spawn(move || { + let _lock = DirLock::lock_exclusive(lock_path_clone).expect("Failed to lock exclusive"); + barrier_clone.wait(); // Signal Thread B that A holds the lock. + + // Simulate brief work holding the lock. + std::thread::sleep(std::time::Duration::from_millis(100)); + lock_released_clone.store(true, std::sync::atomic::Ordering::Relaxed); + // _lock drops here, releasing the lock. + }); + + // Thread B waits for Thread A to acquire the lock, then tries to acquire it itself. + let thread_b = std::thread::spawn(move || { + barrier.wait(); // Wait for Thread A to acquire lock. + + // Attempt to acquire lock. This should block until Thread A releases it. + let _lock = DirLock::lock_exclusive(lock_path).expect("Failed to lock exclusive in B"); + + // Assert that B only successfully locked the directory AFTER A released it. + assert!( + lock_released.load(std::sync::atomic::Ordering::Relaxed), + "Thread B acquired lock before Thread A released it!" + ); + }); + + thread_a.join().unwrap(); + thread_b.join().unwrap(); + } + + #[test] + fn test_dir_lock_shared_coexistence() { + let temp_dir = tempfile::tempdir().unwrap(); + let lock_path = temp_dir.path().to_path_buf(); + + // Thread A acquires shared lock. + let lock_a = DirLock::lock_shared(lock_path.clone()).expect("Failed to lock shared"); + + // Thread B should be able to acquire shared lock immediately without blocking. + let lock_b = DirLock::lock_shared(lock_path).expect("Failed to lock shared concurrently"); + + // Both locks are held. + drop(lock_a); + drop(lock_b); + } +} diff --git a/anneal/v2/tests/test_prune_lake_cache.py b/anneal/tests/test_prune_lake_cache.py similarity index 100% rename from anneal/v2/tests/test_prune_lake_cache.py rename to anneal/tests/test_prune_lake_cache.py diff --git a/anneal/v2/tests/test_rewrite_lake_vendor.py b/anneal/tests/test_rewrite_lake_vendor.py similarity index 100% rename from anneal/v2/tests/test_rewrite_lake_vendor.py rename to anneal/tests/test_rewrite_lake_vendor.py diff --git a/anneal/.gitattributes b/anneal/v1/.gitattributes similarity index 100% rename from anneal/.gitattributes rename to anneal/v1/.gitattributes diff --git a/anneal/.gitignore b/anneal/v1/.gitignore similarity index 100% rename from anneal/.gitignore rename to anneal/v1/.gitignore diff --git a/anneal/AGENTS.md b/anneal/v1/AGENTS.md similarity index 100% rename from anneal/AGENTS.md rename to anneal/v1/AGENTS.md diff --git a/anneal/v2/Cargo.lock b/anneal/v1/Cargo.lock similarity index 68% rename from anneal/v2/Cargo.lock rename to anneal/v1/Cargo.lock index cd9c673ac1..04bcfa1bdb 100644 --- a/anneal/v2/Cargo.lock +++ b/anneal/v1/Cargo.lock @@ -17,18 +17,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -40,30 +28,14 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.12.16" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "memchr", "unicode-width 0.2.2", ] -[[package]] -name = "anstream" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" -dependencies = [ - "anstyle", - "anstyle-parse 0.2.7", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - [[package]] name = "anstream" version = "1.0.0" @@ -71,7 +43,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse 1.0.0", + "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -85,15 +57,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - [[package]] name = "anstyle-parse" version = "1.0.0" @@ -129,26 +92,11 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "ar_archive_writer" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" -dependencies = [ - "object", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "assert_cmd" -version = "2.2.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" +checksum = "9a686bbee5efb88a82df0621b236e74d925f470e5445d3220a5648b892ec99c9" dependencies = [ "anstyle", "bstr", @@ -159,20 +107,11 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - [[package]] name = "autocfg" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" @@ -204,11 +143,26 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" -version = "2.12.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "block-buffer" @@ -219,15 +173,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "brownstone" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5839ee4f953e811bfdcf223f509cb2c6a3e1447959b0bff459405575bc17f22" -dependencies = [ - "arrayvec", -] - [[package]] name = "bstr" version = "1.12.1" @@ -241,15 +186,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" - -[[package]] -name = "byteorder" -version = "1.5.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytes" @@ -268,13 +207,16 @@ dependencies = [ [[package]] name = "cargo-anneal" -version = "0.1.0-alpha.22" +version = "0.1.0-alpha.24" dependencies = [ "anyhow", - "cargo_metadata", - "charon", + "assert_cmd", + "cargo_metadata 0.23.1", "clap", "clap-cargo", + "console", + "dashmap", + "datatest-stable", "env_logger", "exocrate", "fs2", @@ -282,26 +224,57 @@ dependencies = [ "log", "miette", "pathdiff", + "predicates", + "proc-macro2", + "quote", "rayon", + "regex", "serde", "serde_json", "sha2", + "similar", + "strip-ansi-escapes", + "syn", "tempfile", - "thiserror", - "toml_const", + "thiserror 2.0.18", + "toml", + "ui_test", "walkdir", ] [[package]] name = "cargo-platform" -version = "0.3.3" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" dependencies = [ "serde", "serde_core", ] +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform 0.1.9", + "semver", + "serde", + "serde_json", + "thiserror 1.0.69", +] + [[package]] name = "cargo_metadata" version = "0.23.1" @@ -309,18 +282,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ "camino", - "cargo-platform", + "cargo-platform 0.3.2", "semver", "serde", "serde_json", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "cc" -version = "1.2.63" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -334,62 +307,11 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "charon" -version = "0.1.210" -source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" -dependencies = [ - "annotate-snippets", - "anstream 0.6.21", - "anyhow", - "assert_cmd", - "clap", - "colored", - "convert_case", - "derive_generic_visitor", - "either", - "env_logger", - "extension-traits", - "fraction", - "hashbrown 0.15.5", - "hax-adt-into", - "index_vec", - "indexmap", - "indoc", - "itertools", - "lazy_static", - "log", - "macros", - "nom", - "nom-supreme", - "num-bigint", - "paste", - "petgraph", - "postcard", - "rustc-hash", - "rustc_version", - "serde", - "serde_json", - "serde_stacker", - "serde_state", - "smallvec", - "stacker", - "strip-ansi-escapes", - "take_mut", - "tempfile", - "toml 0.8.23", - "tracing", - "tracing-subscriber", - "tracing-tree", - "ustr", - "which", -] - [[package]] name = "clap" -version = "4.6.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -402,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936551935c8258754bb8216aec040957d261f977303754b9bf1a213518388006" dependencies = [ "anstyle", - "cargo_metadata", + "cargo_metadata 0.23.1", "clap", "serde", "serde_json", @@ -414,7 +336,7 @@ version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream 1.0.0", + "anstream", "anstyle", "clap_lex", "strsim", @@ -422,14 +344,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -439,12 +361,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] -name = "cobs" +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ - "thiserror", + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", ] [[package]] @@ -455,14 +395,19 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" -version = "2.2.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] +[[package]] +name = "comma" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" + [[package]] name = "console" version = "0.16.3" @@ -475,15 +420,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "cpufeatures" version = "0.2.17" @@ -503,10 +439,13 @@ dependencies = [ ] [[package]] -name = "critical-section" -version = "1.2.0" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] [[package]] name = "crossbeam-deque" @@ -544,70 +483,29 @@ dependencies = [ ] [[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_generic_visitor" -version = "0.2.0" +name = "dashmap" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21588db07753dafe6460b13faad18bd7e46548ce91ee38f0bc0f7529b3864b82" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "derive_generic_visitor_macros", + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] -name = "derive_generic_visitor_macros" -version = "0.2.0" +name = "datatest-stable" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3aed1890235ebcf844a24263ecc395c4e57a970f13bcc9948989f22aa051aa7" +checksum = "a867d7322eb69cf3a68a5426387a25b45cb3b9c5ee41023ee6cea92e2afadd82" dependencies = [ - "convert_case", - "darling", - "itertools", - "proc-macro2", - "quote", - "syn 2.0.117", + "camino", + "fancy-regex", + "libtest-mimic", + "walkdir", ] [[package]] @@ -648,22 +546,18 @@ dependencies = [ ] [[package]] -name = "either" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +name = "doc_gen" +version = "0.1.0" +dependencies = [ + "tree-sitter", + "tree-sitter-lean4", +] [[package]] -name = "embedded-io" -version = "0.6.1" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" @@ -681,19 +575,13 @@ dependencies = [ "regex", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "env_logger" version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ - "anstream 1.0.0", + "anstream", "anstyle", "env_filter", "jiff", @@ -716,6 +604,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "escape8259" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" + [[package]] name = "exocrate" version = "0.1.0" @@ -732,48 +626,41 @@ dependencies = [ ] [[package]] -name = "ext-trait" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5" -dependencies = [ - "ext-trait-proc_macros", -] - -[[package]] -name = "ext-trait-proc_macros" -version = "1.0.1" +name = "eyre" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "indenter", + "once_cell", ] [[package]] -name = "extension-traits" -version = "1.0.1" +name = "fancy-regex" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" dependencies = [ - "ext-trait", + "bit-set", + "regex-automata", + "regex-syntax", ] [[package]] name = "fastrand" -version = "2.4.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "filetime" -version = "0.2.29" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", + "libredox", ] [[package]] @@ -782,12 +669,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - [[package]] name = "flate2" version = "1.1.9" @@ -799,10 +680,13 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" +name = "float-cmp" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] [[package]] name = "foldhash" @@ -810,16 +694,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "fraction" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" -dependencies = [ - "lazy_static", - "num", -] - [[package]] name = "fs2" version = "0.4.3" @@ -830,30 +704,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -907,13 +757,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] -name = "hash32" -version = "0.2.1" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" @@ -926,35 +773,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "hax-adt-into" -version = "0.3.5" -source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "syn 1.0.109", - "tracing", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -964,9 +785,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", "itoa", @@ -985,34 +806,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indent_write" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" - -[[package]] -name = "index_vec" -version = "0.1.4" +name = "indenter" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" -dependencies = [ - "serde", -] +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" -version = "2.14.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown 0.16.1", "serde", "serde_core", ] @@ -1031,15 +837,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - [[package]] name = "is_ci" version = "1.2.0" @@ -1052,15 +849,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.18" @@ -1069,9 +857,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.28" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", @@ -1082,13 +870,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.28" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1101,20 +889,12 @@ dependencies = [ "libc", ] -[[package]] -name = "joinery" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" - [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ - "cfg-if", - "futures-util", "once_cell", "wasm-bindgen", ] @@ -1131,19 +911,40 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +[[package]] +name = "levenshtein" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" + [[package]] name = "libc" -version = "0.2.186" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ + "bitflags", "libc", + "plain", + "redox_syscall 0.7.3", +] + +[[package]] +name = "libtest-mimic" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e6ba06f0ade6e504aff834d7c34298e5155c6baca353cc6a4aaff2f9fd7f33" +dependencies = [ + "anstream", + "anstyle", + "clap", + "escape8259", ] [[package]] @@ -1163,34 +964,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" - -[[package]] -name = "macros" -version = "0.1.0" -source = "git+https://github.com/AeneasVerif/charon.git?tag=nightly-2026.06.03#0c91ca1a8e002d6bfa8d8f1f452804fce2f92cf1" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "matchers" -version = "0.2.0" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "miette" @@ -1219,15 +1001,9 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1239,106 +1015,10 @@ dependencies = [ ] [[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom-supreme" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd3ae6c901f1959588759ff51c95d24b491ecb9ff91aa9c2ef4acc5b1dcab27" -dependencies = [ - "brownstone", - "indent_write", - "joinery", - "memchr", - "nom", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" +name = "normalize-line-endings" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-traits" @@ -1349,15 +1029,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.37.3" @@ -1391,16 +1062,6 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - [[package]] name = "parking_lot_core" version = "0.9.12" @@ -1409,17 +1070,11 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pathdiff" version = "0.2.3" @@ -1432,61 +1087,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap", - "serde", -] - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_macros", - "phf_shared", - "serde", -] - -[[package]] -name = "phf_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" -dependencies = [ - "fastrand", - "phf_shared", -] - -[[package]] -name = "phf_macros" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1495,9 +1095,15 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "portable-atomic" @@ -1507,32 +1113,13 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] -[[package]] -name = "postcard" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" -dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "heapless", - "serde", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "predicates" version = "3.1.4" @@ -1541,7 +1128,10 @@ checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "difflib", + "float-cmp", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -1554,10 +1144,19 @@ checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" name = "predicates-tree" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettydiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac17546d82912e64874e3d5b40681ce32eac4e5834344f51efcf689ff1550a65" dependencies = [ - "predicates-core", - "termtree", + "owo-colors", ] [[package]] @@ -1567,7 +1166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn", ] [[package]] @@ -1579,16 +1178,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "psm" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea" -dependencies = [ - "ar_archive_writer", - "cc", -] - [[package]] name = "quote" version = "1.0.45" @@ -1612,9 +1201,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rayon" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -1639,6 +1228,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -1647,7 +1245,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror", + "thiserror 2.0.18", ] [[package]] @@ -1699,12 +1297,6 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - [[package]] name = "rustc_version" version = "0.4.1" @@ -1714,6 +1306,18 @@ dependencies = [ "semver", ] +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1729,9 +1333,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "log", "once_cell", @@ -1744,9 +1348,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] @@ -1785,9 +1389,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.28" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", "serde_core", @@ -1820,15 +1424,16 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ + "indexmap", "itoa", "memchr", "serde", @@ -1845,45 +1450,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_stacker" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4936375d50c4be7eff22293a9344f8e46f323ed2b3c243e52f89138d9bb0f4a" -dependencies = [ - "serde", - "serde_core", - "stacker", -] - -[[package]] -name = "serde_state" -version = "1.0.0" -source = "git+https://github.com/Nadrieril/serde_state?branch=main#9bffbc1b28fd93533bbd3ca835385f29cb51888f" -dependencies = [ - "serde", - "serde_state_derive", -] - -[[package]] -name = "serde_state_derive" -version = "1.0.0" -source = "git+https://github.com/Nadrieril/serde_state?branch=main#9bffbc1b28fd93533bbd3ca835385f29cb51888f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "sha2" version = "0.10.9" @@ -1912,9 +1478,9 @@ dependencies = [ [[package]] name = "shlex" -version = "2.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simd-adler32" @@ -1923,16 +1489,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] -name = "siphasher" -version = "1.0.3" +name = "similar" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "smallvec" @@ -1941,32 +1501,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "spin" -version = "0.9.8" +name = "spanned" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "c92d4b0c055fde758f086eb4a6e73410247df8a3837fd606d2caeeaf72aa566d" dependencies = [ - "lock_api", + "anyhow", + "bstr", + "color-eyre", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stacker" -version = "0.1.24" +name = "streaming-iterator" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.61.2", -] +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" [[package]] name = "strip-ansi-escapes" @@ -2010,17 +1559,6 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.117" @@ -2032,12 +1570,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "take_mut" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" - [[package]] name = "tar" version = "0.4.46" @@ -2090,64 +1622,51 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", ] [[package]] -name = "thiserror-impl" +name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "thiserror-impl 2.0.18", ] [[package]] -name = "thread_local" -version = "1.1.9" +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "time" -version = "0.3.47" +name = "thiserror-impl" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde_core", - "time-core", - "time-macros", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" +name = "thread_local" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "num-conv", - "time-core", + "cfg-if", ] [[package]] @@ -2157,50 +1676,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", + "serde_spanned", + "toml_datetime", "toml_edit", ] -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - -[[package]] -name = "toml_const" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389864cf501669b741746e9bc35e66c67f2b80266482ad04c452e2410433f205" -dependencies = [ - "phf", - "toml 0.9.12+spec-1.1.0", - "toml_const_macros", -] - -[[package]] -name = "toml_const_macros" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e0f202adfb96027640ad9786a0657775414482cfd840c19e9957ada8cfbbfd" -dependencies = [ - "indexmap", - "proc-macro2", - "quote", - "syn 2.0.117", - "toml 0.9.12+spec-1.1.0", -] - [[package]] name = "toml_datetime" version = "0.6.11" @@ -2210,15 +1690,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - [[package]] name = "toml_edit" version = "0.22.27" @@ -2227,19 +1698,10 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", + "serde_spanned", + "toml_datetime", "toml_write", - "winnow 0.7.15", -] - -[[package]] -name = "toml_parser" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" -dependencies = [ - "winnow 1.0.3", + "winnow", ] [[package]] @@ -2248,12 +1710,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "toml_writer" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" - [[package]] name = "tracing" version = "0.1.44" @@ -2261,21 +1717,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "tracing-core" version = "0.1.36" @@ -2287,14 +1731,13 @@ dependencies = [ ] [[package]] -name = "tracing-log" -version = "0.2.0" +name = "tracing-error" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ - "log", - "once_cell", - "tracing-core", + "tracing", + "tracing-subscriber", ] [[package]] @@ -2303,35 +1746,72 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", "sharded-slab", - "smallvec", "thread_local", - "tracing", "tracing-core", - "tracing-log", ] [[package]] -name = "tracing-tree" -version = "0.4.0" -source = "git+https://github.com/Nadrieril/tracing-tree#841286bfffd3c2200810244506cd127013dbeff9" +name = "tree-sitter" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" dependencies = [ - "nu-ansi-term", - "time", - "tracing-core", - "tracing-log", - "tracing-subscriber", + "cc", + "regex", + "regex-syntax", + "serde_json", + "streaming-iterator", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-language" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" + +[[package]] +name = "tree-sitter-lean4" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d274c5b559d3a46a0d5d200fc0593fa3fda035304fa794d5d4a760fbf69c2a5e" +dependencies = [ + "cc", + "tree-sitter", ] [[package]] name = "typenum" -version = "1.20.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "ui_test" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada249620d81f010b9a1472b63a5077ac7c722dd0f4bacf6528b313d0b8c15d8" +dependencies = [ + "annotate-snippets", + "anyhow", + "bstr", + "cargo-platform 0.1.9", + "cargo_metadata 0.18.1", + "color-eyre", + "colored", + "comma", + "crossbeam-channel", + "indicatif", + "levenshtein", + "prettydiff", + "regex", + "rustc_version", + "rustfix", + "serde", + "serde_json", + "spanned", +] [[package]] name = "unicode-ident" @@ -2347,9 +1827,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-segmentation" -version = "1.13.3" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -2410,19 +1890,6 @@ dependencies = [ "log", ] -[[package]] -name = "ustr" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208" -dependencies = [ - "ahash", - "byteorder", - "lazy_static", - "parking_lot", - "serde", -] - [[package]] name = "utf8-zero" version = "0.8.1" @@ -2483,11 +1950,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen 0.57.1", + "wit-bindgen", ] [[package]] @@ -2496,14 +1963,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", @@ -2514,9 +1981,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2524,22 +1991,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -2590,25 +2057,13 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "7.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" -dependencies = [ - "either", - "env_home", - "rustix", - "winsafe", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2655,15 +2110,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -2746,18 +2192,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" - -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -2767,12 +2201,6 @@ dependencies = [ "wit-bindgen-rust-macro", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -2794,7 +2222,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -2810,7 +2238,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -2862,26 +2290,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "zerocopy" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "zeroize" version = "1.8.2" diff --git a/anneal/v1/Cargo.toml b/anneal/v1/Cargo.toml new file mode 100644 index 0000000000..f545b31c8e --- /dev/null +++ b/anneal/v1/Cargo.toml @@ -0,0 +1,112 @@ +[workspace] +members = [".", "tools/doc_gen"] + +[package] +name = "cargo-anneal" +edition = "2024" +version = "0.1.0-alpha.24" +description = "Formally verify that your safety comments are correct." +categories = [ + "development-tools::cargo-plugins", + "development-tools::testing", + "compilers", + "mathematics", + "security", +] +keywords = ["verification", "cargo", "plugin", "unsafe", "lean"] +license = "BSD-2-Clause OR Apache-2.0 OR MIT" +repository = "https://github.com/google/zerocopy/tree/main/anneal/v1" +publish = true + +exclude = [".*", "testdata"] + +# FIXME: Replace these placeholder archive URLs and hashes before publishing +# this crate; `cargo anneal setup` uses this metadata by default when callers +# do not provide a local archive. +[package.metadata.exocrate.linux.x86_64] +sha256 = "d3d7bbcdfd2645f10e3e64a85b3e848197033992337c969a45576a3d0ec517d9" +url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-linux-x86_64.tar.zst" + +[package.metadata.exocrate.macos.x86_64] +sha256 = "1252f15262d11f49795c8ed182a8b47f2ae4e627d90babb2f10636349f686438" +url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-macos-x86_64.tar.zst" + +[package.metadata.exocrate.linux.aarch64] +sha256 = "a9c496fcf21670b2306d02722b9afcf375149315e929d53b6a7585d4daa19710" +url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-linux-aarch64.tar.zst" + +[package.metadata.exocrate.macos.aarch64] +sha256 = "b4e0a5b420eb441e37564c365f06c215f61a3b825fc3df37293da7c3010d2b81" +url = "https://github.com/google/zerocopy/releases/download/anneal-toolchains-v0.1.0-alpha.24-27079750833-09497849a10d/anneal-toolchain-macos-aarch64.tar.zst" + +[dependencies] +anyhow = "1.0.102" +cargo_metadata = "0.23.1" +clap = { version = "4.6.0", features = ["derive"] } +clap-cargo = { version = "0.18.3", features = ["cargo_metadata"] } +dashmap = "6.1.0" +env_logger = "0.11.10" +log = "0.4.29" +miette = { version = "7.6.0", features = ["derive", "fancy"] } +proc-macro2 = { version = "1.0.106", features = ["span-locations"] } +rayon = "1.11.0" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.149" +syn = { version = "2.0.117", features = [ + "full", + "visit", + "extra-traits", + "parsing", + "printing", +] } +quote = "1.0" +thiserror = "2.0.18" +walkdir = "2.5.0" +indicatif = { version = "0.18.4", features = ["improved_unicode"] } +console = "0.16.3" +exocrate = { path = "../../exocrate" } +sha2 = "0.10" +fs2 = "0.4" +pathdiff = "0.2.3" +toml = "0.8" +tempfile = "3.27.0" + +[build-dependencies] +sha2 = "0.10" +toml = "0.8" + +[dev-dependencies] +syn = { version = "2.0.117", features = [ + "printing", + "full", + "visit", + "extra-traits", + "parsing", +] } +proc-macro2 = { version = "1.0.106", features = ["span-locations"] } +ui_test = "0.30.4" +assert_cmd = "2.2.0" + +predicates = "3.1.4" + +datatest-stable = "0.3.3" +serde = { version = "1.0", features = ["derive"] } +toml = "0.8" +regex = "1.0" +strip-ansi-escapes = "0.2.1" +similar = "2.7.0" + +[package.metadata.build_rs] + +# The commit hash of the Aeneas repository to use. +# +# FIXME: Add a CI step to verify that this commit exists and matches the +# toolchain version. +aeneas_rev = "42c0e90dacf486f7d3ed5b6cde3a9a81f04915a4" + +# The Lean toolchain version to use. This must match the version of Lean used +# by Aeneas in the `lean-toolchain` file in the commit above. +lean_toolchain = "leanprover/lean4:v4.30.0-rc2" +[[test]] +name = "integration" +harness = false diff --git a/anneal/Dockerfile b/anneal/v1/Dockerfile similarity index 94% rename from anneal/Dockerfile rename to anneal/v1/Dockerfile index 37a9a03d84..6a0c6482c9 100644 --- a/anneal/Dockerfile +++ b/anneal/v1/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.11-slim AS extractor WORKDIR /app -COPY anneal/Cargo.toml ./ +COPY anneal/v1/Cargo.toml ./ # Remove the [workspace] section so it can be built as a standalone package. # Also inject tree-sitter dependencies used by doc_gen to cache them too. RUN sed '1,2d' Cargo.toml > Cargo.toml.no_workspace && \ @@ -51,17 +51,17 @@ ENV ANNEAL_INTEGRATION_TARGET_DIR=/cache/anneal_target # via a volume mount, causing dependencies to be rebuilt once in the volume. # This double-build is intentional to support both environments efficiently. ENV CARGO_TARGET_DIR=/opt/anneal_target -WORKDIR /workspace/anneal +WORKDIR /workspace/anneal/v1 # Copy the workspace configuration (without workspace section) and lockfile. COPY --from=extractor --chown=anneal:anneal /app/Cargo.toml.no_workspace ./Cargo.toml -COPY --chown=anneal:anneal anneal/Cargo.lock ./ +COPY --chown=anneal:anneal anneal/v1/Cargo.lock ./ # Copy source files needed to compile dependency-heavy modules. -COPY --chown=anneal:anneal anneal/src/setup.rs ./src/ +COPY --chown=anneal:anneal anneal/v1/src/setup.rs ./src/ COPY --chown=anneal:anneal exocrate/Cargo.toml /workspace/exocrate/Cargo.toml COPY --chown=anneal:anneal exocrate/src /workspace/exocrate/src -COPY --chown=anneal:anneal anneal/build.rs ./ +COPY --chown=anneal:anneal anneal/v1/build.rs ./ # Create a minimal `main.rs` and a dummy test file. # This allows us to build dependencies in the image without copying the full diff --git a/anneal/v1/LICENSE-APACHE b/anneal/v1/LICENSE-APACHE new file mode 120000 index 0000000000..1cd601d0a3 --- /dev/null +++ b/anneal/v1/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/anneal/v1/LICENSE-BSD b/anneal/v1/LICENSE-BSD new file mode 120000 index 0000000000..0af6dcc0d3 --- /dev/null +++ b/anneal/v1/LICENSE-BSD @@ -0,0 +1 @@ +../../LICENSE-BSD \ No newline at end of file diff --git a/anneal/v1/LICENSE-MIT b/anneal/v1/LICENSE-MIT new file mode 120000 index 0000000000..b2cfbdc7b0 --- /dev/null +++ b/anneal/v1/LICENSE-MIT @@ -0,0 +1 @@ +../../LICENSE-MIT \ No newline at end of file diff --git a/anneal/README.md b/anneal/v1/README.md similarity index 100% rename from anneal/README.md rename to anneal/v1/README.md diff --git a/anneal/build.rs b/anneal/v1/build.rs similarity index 100% rename from anneal/build.rs rename to anneal/v1/build.rs diff --git a/anneal/docker.sh b/anneal/v1/docker.sh similarity index 97% rename from anneal/docker.sh rename to anneal/v1/docker.sh index d0d9ae3085..740f788df6 100755 --- a/anneal/docker.sh +++ b/anneal/v1/docker.sh @@ -36,10 +36,10 @@ fi # Resolve the directory paths required to build the image and mount the # workspace volume into the container. The Docker build context is the repo -# worktree root so the Dockerfile can copy both `anneal/` and the root-level +# worktree root so the Dockerfile can copy both `anneal/v1/` and the root-level # `exocrate/` crate. ANNEAL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" -WORKTREE_DIR="$(cd "$ANNEAL_DIR/.." >/dev/null 2>&1 && pwd)" +WORKTREE_DIR="$(cd "$ANNEAL_DIR/../.." >/dev/null 2>&1 && pwd)" # To avoid pollution between different git worktrees, we generate a unique # worktree ID and store it in a file. This ensures each worktree gets its own # isolated cache volume and Docker image tag. @@ -187,7 +187,7 @@ done # Determine the user's current working directory relative to the repository. # This path is passed to Docker so that the container executes the requested # command in the same relative directory as the caller. -REL_PATH=$(realpath --relative-to="$WORKTREE_DIR" "$(pwd)" 2>/dev/null || echo "anneal") +REL_PATH=$(realpath --relative-to="$WORKTREE_DIR" "$(pwd)" 2>/dev/null || echo "anneal/v1") WORKDIR="/workspace/$REL_PATH" exec "${DOCKER_CMD[@]}" run "${DOCKER_FLAGS[@]}" \ diff --git a/anneal/docs/agent/01_philosophy_and_pipeline.md b/anneal/v1/docs/agent/01_philosophy_and_pipeline.md similarity index 100% rename from anneal/docs/agent/01_philosophy_and_pipeline.md rename to anneal/v1/docs/agent/01_philosophy_and_pipeline.md diff --git a/anneal/docs/agent/02_rust_to_lean_mapping.md b/anneal/v1/docs/agent/02_rust_to_lean_mapping.md similarity index 100% rename from anneal/docs/agent/02_rust_to_lean_mapping.md rename to anneal/v1/docs/agent/02_rust_to_lean_mapping.md diff --git a/anneal/docs/agent/03_memory_model.md b/anneal/v1/docs/agent/03_memory_model.md similarity index 100% rename from anneal/docs/agent/03_memory_model.md rename to anneal/v1/docs/agent/03_memory_model.md diff --git a/anneal/docs/agent/04_specifications_and_syntax.md b/anneal/v1/docs/agent/04_specifications_and_syntax.md similarity index 100% rename from anneal/docs/agent/04_specifications_and_syntax.md rename to anneal/v1/docs/agent/04_specifications_and_syntax.md diff --git a/anneal/docs/agent/05_proof_architecture.md b/anneal/v1/docs/agent/05_proof_architecture.md similarity index 100% rename from anneal/docs/agent/05_proof_architecture.md rename to anneal/v1/docs/agent/05_proof_architecture.md diff --git a/anneal/docs/agent/06_tactics_and_tooling.md b/anneal/v1/docs/agent/06_tactics_and_tooling.md similarity index 100% rename from anneal/docs/agent/06_tactics_and_tooling.md rename to anneal/v1/docs/agent/06_tactics_and_tooling.md diff --git a/anneal/docs/agent/07_workflow.md b/anneal/v1/docs/agent/07_workflow.md similarity index 100% rename from anneal/docs/agent/07_workflow.md rename to anneal/v1/docs/agent/07_workflow.md diff --git a/anneal/docs/design/design.md b/anneal/v1/docs/design/design.md similarity index 100% rename from anneal/docs/design/design.md rename to anneal/v1/docs/design/design.md diff --git a/anneal/docs/design/named_bounds.md b/anneal/v1/docs/design/named_bounds.md similarity index 100% rename from anneal/docs/design/named_bounds.md rename to anneal/v1/docs/design/named_bounds.md diff --git a/anneal/docs/images/logo.svg b/anneal/v1/docs/images/logo.svg similarity index 100% rename from anneal/docs/images/logo.svg rename to anneal/v1/docs/images/logo.svg diff --git a/anneal/examples/abs.rs b/anneal/v1/examples/abs.rs similarity index 100% rename from anneal/examples/abs.rs rename to anneal/v1/examples/abs.rs diff --git a/anneal/examples/anatomy.rs b/anneal/v1/examples/anatomy.rs similarity index 100% rename from anneal/examples/anatomy.rs rename to anneal/v1/examples/anatomy.rs diff --git a/anneal/examples/checked_add.rs b/anneal/v1/examples/checked_add.rs similarity index 100% rename from anneal/examples/checked_add.rs rename to anneal/v1/examples/checked_add.rs diff --git a/anneal/examples/const_generics.rs b/anneal/v1/examples/const_generics.rs similarity index 100% rename from anneal/examples/const_generics.rs rename to anneal/v1/examples/const_generics.rs diff --git a/anneal/examples/design_doc.rs b/anneal/v1/examples/design_doc.rs similarity index 100% rename from anneal/examples/design_doc.rs rename to anneal/v1/examples/design_doc.rs diff --git a/anneal/examples/linked_list.rs b/anneal/v1/examples/linked_list.rs similarity index 100% rename from anneal/examples/linked_list.rs rename to anneal/v1/examples/linked_list.rs diff --git a/anneal/examples/namespaces.rs b/anneal/v1/examples/namespaces.rs similarity index 100% rename from anneal/examples/namespaces.rs rename to anneal/v1/examples/namespaces.rs diff --git a/anneal/examples/never_type.rs b/anneal/v1/examples/never_type.rs similarity index 100% rename from anneal/examples/never_type.rs rename to anneal/v1/examples/never_type.rs diff --git a/anneal/examples/nopanic.rs b/anneal/v1/examples/nopanic.rs similarity index 100% rename from anneal/examples/nopanic.rs rename to anneal/v1/examples/nopanic.rs diff --git a/anneal/examples/positive_usize.rs b/anneal/v1/examples/positive_usize.rs similarity index 100% rename from anneal/examples/positive_usize.rs rename to anneal/v1/examples/positive_usize.rs diff --git a/anneal/examples/ptr_concat.rs b/anneal/v1/examples/ptr_concat.rs similarity index 100% rename from anneal/examples/ptr_concat.rs rename to anneal/v1/examples/ptr_concat.rs diff --git a/anneal/examples/size_of_align_of.rs b/anneal/v1/examples/size_of_align_of.rs similarity index 100% rename from anneal/examples/size_of_align_of.rs rename to anneal/v1/examples/size_of_align_of.rs diff --git a/anneal/examples/swap.rs b/anneal/v1/examples/swap.rs similarity index 100% rename from anneal/examples/swap.rs rename to anneal/v1/examples/swap.rs diff --git a/anneal/examples/unchecked_get.rs b/anneal/v1/examples/unchecked_get.rs similarity index 100% rename from anneal/examples/unchecked_get.rs rename to anneal/v1/examples/unchecked_get.rs diff --git a/anneal/examples/update_max.rs b/anneal/v1/examples/update_max.rs similarity index 100% rename from anneal/examples/update_max.rs rename to anneal/v1/examples/update_max.rs diff --git a/anneal/llms-full.txt b/anneal/v1/llms-full.txt similarity index 100% rename from anneal/llms-full.txt rename to anneal/v1/llms-full.txt diff --git a/anneal/llms.txt b/anneal/v1/llms.txt similarity index 100% rename from anneal/llms.txt rename to anneal/v1/llms.txt diff --git a/anneal/src/Anneal.lean b/anneal/v1/src/Anneal.lean similarity index 100% rename from anneal/src/Anneal.lean rename to anneal/v1/src/Anneal.lean diff --git a/anneal/src/aeneas.rs b/anneal/v1/src/aeneas.rs similarity index 100% rename from anneal/src/aeneas.rs rename to anneal/v1/src/aeneas.rs diff --git a/anneal/src/charon.rs b/anneal/v1/src/charon.rs similarity index 100% rename from anneal/src/charon.rs rename to anneal/v1/src/charon.rs diff --git a/anneal/src/diagnostics.rs b/anneal/v1/src/diagnostics.rs similarity index 100% rename from anneal/src/diagnostics.rs rename to anneal/v1/src/diagnostics.rs diff --git a/anneal/src/errors.rs b/anneal/v1/src/errors.rs similarity index 100% rename from anneal/src/errors.rs rename to anneal/v1/src/errors.rs diff --git a/anneal/src/generate.rs b/anneal/v1/src/generate.rs similarity index 100% rename from anneal/src/generate.rs rename to anneal/v1/src/generate.rs diff --git a/anneal/v1/src/main.rs b/anneal/v1/src/main.rs new file mode 100644 index 0000000000..3d363b977d --- /dev/null +++ b/anneal/v1/src/main.rs @@ -0,0 +1,184 @@ +mod aeneas; +mod charon; +mod diagnostics; +mod errors; +mod generate; +mod parse; +mod resolve; +mod scanner; +mod validate; + +mod setup; +mod ui_test_shim; +mod util; + +use clap::Parser; + +/// Anneal: A Literate Verification Toolchain +#[derive(Parser, Debug)] +#[command(name = "cargo-anneal", version, about, long_about = None)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(clap::Subcommand, Debug)] +enum Commands { + /// Verify a crate + Verify(resolve::Args), + /// Setup Anneal dependencies + Setup(resolve::SetupArgs), + /// Expand a crate's Lean output + Expand(ExpandArgs), + /// Generate Lean workspace and print paths without building + Generate(resolve::Args), + #[command(hide = true)] + ToolchainPath, +} + +#[derive(clap::ValueEnum, Clone, Debug, Default, PartialEq)] +pub enum EmitFormat { + #[default] + All, + Anneal, + Aeneas, +} + +#[derive(Parser, Debug)] +pub struct ExpandArgs { + #[command(flatten)] + pub resolve_args: resolve::Args, + + /// Which tool's generated Lean code to output + #[arg(long, default_value_t, value_enum)] + pub emit: EmitFormat, +} + +fn main() -> anyhow::Result<()> { + // Suppressing timestamps removes a source of nondeterminism that is + // difficult to work around in integration tests. + env_logger::builder().format_timestamp(None).init(); + + if std::env::var("ANNEAL_UI_TEST_MODE").is_ok() { + ui_test_shim::run(); + return Ok(()); + } + + let mut args_iter = std::env::args_os().peekable(); + let bin_name = args_iter.next().unwrap_or_else(|| "cargo-anneal".into()); + // If we're being run as a cargo plugin, the second argument will be "anneal". + if args_iter.peek().is_some_and(|arg| arg == "anneal") { + args_iter.next(); + } + let args = Cli::parse_from(std::iter::once(bin_name).chain(args_iter)); + + match args.command { + Commands::Verify(resolve_args) => { + prepare_and_run(&resolve_args, |locked_roots, packages| { + aeneas::verify_lean_workspace(locked_roots, packages) + })?; + } + Commands::Generate(resolve_args) => { + prepare_and_run(&resolve_args, |locked_roots, packages| { + aeneas::generate_lean_workspace(locked_roots, packages)?; + let lean_root = locked_roots.lean_root(); + let toolchain = setup::Toolchain::resolve()?; + println!("Lean workspace generated at: {}", lean_root.display()); + println!(); + println!("To manually build and experiment:"); + println!(" 1. cd {}", lean_root.display()); + println!( + " 2. LAKE_CACHE_DIR={} {} --keep-toolchain build", + toolchain.cache_dir().display(), + toolchain.lean_bin().join("lake").display() + ); + Ok(()) + })?; + } + Commands::Setup(args) => { + setup::run_setup(setup::SetupArgs { local_archive: args.local_archive })?; + } + Commands::ToolchainPath => { + let toolchain = setup::Toolchain::resolve()?; + println!("{}", toolchain.bin_dir().display()); + } + Commands::Expand(expand_args) => { + prepare_and_run(&expand_args.resolve_args, |locked_roots, packages| { + let lean_generated_root = locked_roots.lean_generated_root(); + + for artifact in packages { + if artifact.start_from.is_empty() { + continue; + } + + let slug = artifact.artifact_slug(); + let output_dir = lean_generated_root.join(&slug); + + let emit_all = expand_args.emit == EmitFormat::All; + let emit_anneal = emit_all || expand_args.emit == EmitFormat::Anneal; + let emit_aeneas = emit_all || expand_args.emit == EmitFormat::Aeneas; + + println!("=== Lean expansion for: {} ===", artifact.name.target_name); + + if emit_aeneas { + println!("--- Aeneas ---"); + // Read Aeneas outputs from disk + let types_path = output_dir.join("Types.lean"); + let types_ext_path = output_dir.join("TypesExternal.lean"); + let funs_path = output_dir.join("Funs.lean"); + let funs_ext_path = output_dir.join("FunsExternal.lean"); + + if types_path.exists() { + println!("{}", std::fs::read_to_string(&types_path)?); + } + if types_ext_path.exists() { + println!("{}", std::fs::read_to_string(&types_ext_path)?); + } + if funs_path.exists() { + println!("{}", std::fs::read_to_string(&funs_path)?); + } + if funs_ext_path.exists() { + println!("{}", std::fs::read_to_string(&funs_ext_path)?); + } + } + + if emit_anneal { + println!("--- Anneal ---"); + let generated = generate::generate_artifact(artifact); + println!("{}", generated.code); + } + } + + Ok(()) + })?; + } + } + + Ok(()) +} + +fn prepare_and_run(resolve_args: &resolve::Args, f: F) -> anyhow::Result> +where + F: FnOnce(&resolve::LockedRoots, &[scanner::AnnealArtifact]) -> anyhow::Result, +{ + let roots = resolve::resolve_roots(resolve_args)?; + + let packages = scanner::scan_workspace(&roots)?; + if packages.is_empty() { + log::warn!( + "No Anneal annotations (/// ```lean ...) found in the selected targets. Nothing to verify." + ); + return Ok(None); + } + + let locked_roots = roots.lock_run_root()?; + validate::validate_artifacts( + &packages, + resolve_args.allow_sorry, + resolve_args.unsound_allow_is_valid, + )?; + charon::run_charon(resolve_args, &locked_roots, &packages)?; + aeneas::run_aeneas(&locked_roots, &packages, resolve_args)?; + + Ok(Some(f(&locked_roots, &packages)?)) +} diff --git a/anneal/src/parse/attr.rs b/anneal/v1/src/parse/attr.rs similarity index 100% rename from anneal/src/parse/attr.rs rename to anneal/v1/src/parse/attr.rs diff --git a/anneal/src/parse/hkd.rs b/anneal/v1/src/parse/hkd.rs similarity index 100% rename from anneal/src/parse/hkd.rs rename to anneal/v1/src/parse/hkd.rs diff --git a/anneal/src/parse/mod.rs b/anneal/v1/src/parse/mod.rs similarity index 100% rename from anneal/src/parse/mod.rs rename to anneal/v1/src/parse/mod.rs diff --git a/anneal/v2/src/resolve.rs b/anneal/v1/src/resolve.rs similarity index 61% rename from anneal/v2/src/resolve.rs rename to anneal/v1/src/resolve.rs index a87fa5cde0..9a44f65296 100644 --- a/anneal/v2/src/resolve.rs +++ b/anneal/v1/src/resolve.rs @@ -1,30 +1,13 @@ -// Copyright 2026 The Fuchsia Authors -// -// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 -// , or the MIT -// license , at your option. -// This file may not be copied, modified, or distributed except according to -// those terms. - -//! Cargo package and target resolution for Anneal. -//! -//! Cargo selectors can identify several compilation artifacts depending on -//! package layout: default selection may include libraries and binaries, -//! `--tests` can build test harnesses plus supporting targets, and a library -//! target can expose several crate types such as `rlib` and `cdylib`. -//! -//! This module resolves that selection into one explicit Anneal artifact per -//! package target and target kind. Downstream stages process those artifacts -//! independently, assigning each its own LLBC path and Charon configuration. -//! This prevents selected rustc units from sharing a `--dest-file`, avoids -//! collisions between workspace packages with the same Rust crate name, and -//! permits per-target Charon options such as `--start-from` and `--opaque`. - -use anyhow::Context as _; -use sha2::Digest as _; - -#[derive(clap::Parser, Debug)] +use std::{env, fs, path::PathBuf}; + +use anyhow::{Context, Result, anyhow}; +use cargo_metadata::{Metadata, MetadataCommand, Package, PackageName, Target, TargetKind}; +use clap::Parser; +use sha2::{Digest, Sha256}; + +use crate::util::DirLock; + +#[derive(Parser, Debug)] pub struct Args { #[command(flatten)] pub manifest: clap_cargo::Manifest, @@ -35,40 +18,60 @@ pub struct Args { #[command(flatten)] pub features: clap_cargo::Features, - /// Verify the library target. + /// Verify the library target #[arg(long)] pub lib: bool, - /// Verify specific binary targets. + /// Verify specific binary targets #[arg(long)] pub bin: Vec, - /// Verify all binary targets. + /// Verify all binary targets #[arg(long)] pub bins: bool, - /// Verify specific example targets. + /// Verify specific example targets #[arg(long)] pub example: Vec, - /// Verify all example targets. + /// Verify all example targets #[arg(long)] pub examples: bool, - /// Verify specific test targets. + /// Verify specific test targets #[arg(long)] pub test: Vec, - /// Verify all test targets. + /// Verify all test targets #[arg(long)] pub tests: bool, - /// Permit Lean proof admissions (`sorry`, `admit`, or `sorryAx`). - /// - /// Without this explicit opt-in, generated Lean treats warnings as errors - /// so every declaration which semantically depends on an admission fails. + /// Allow `sorry` in proofs and inject `sorry` for missing proofs #[arg(long)] pub allow_sorry: bool, + + /// Allow use of `isValid` annotations + /// + /// `isValid` annotations are currently unsound. In particular, Rust does + /// not yet support annotating a field with `unsafe`, denoting that it + /// carries an invariant. Thus, `isValid` annotations are effectively + /// advisory – any code which does not have a Anneal annotation can modify + /// invariant-carrying fields without needing to use an `unsafe` block. + /// Without an `unsafe` block, Anneal has no way of knowing that an + /// operation needs to be analyzed for soundness. + /// + /// Once the `syn` parser supports parsing `unsafe` fields (which are + /// already supported in a nightly Rust feature), Anneal will require that + /// `isValid` is only used on `unsafe` fields. + #[arg(long)] + pub unsound_allow_is_valid: bool, +} + +#[derive(Parser, Debug)] +pub struct SetupArgs { + /// Install dependencies from a locally built exocrate archive. + #[arg(long, value_name = "path-to-local-archive")] + pub local_archive: Option, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -94,21 +97,23 @@ pub enum AnnealTargetKind { Test, } +// We map `cargo_metadata::TargetKind` to our own `AnnealTargetKind` to +// strictly validate supported target types and simplify downstream logic. +// While `cargo_metadata` is exhaustive, we only care about a subset of +// targets relevant to verification. + impl AnnealTargetKind { pub fn is_lib(&self) -> bool { use AnnealTargetKind::*; - match self { - Lib | RLib | ProcMacro | CDyLib | DyLib | StaticLib => true, - Bin | Example | Test => false, - } + matches!(self, Lib | RLib | ProcMacro | CDyLib | DyLib | StaticLib) } } -impl std::convert::TryFrom<&cargo_metadata::TargetKind> for AnnealTargetKind { +impl TryFrom<&TargetKind> for AnnealTargetKind { type Error = (); - fn try_from(kind: &cargo_metadata::TargetKind) -> anyhow::Result { - use cargo_metadata::TargetKind::*; + fn try_from(kind: &TargetKind) -> Result { + use TargetKind::*; match kind { Lib => Ok(Self::Lib), RLib => Ok(Self::RLib), @@ -127,15 +132,8 @@ impl std::convert::TryFrom<&cargo_metadata::TargetKind> for AnnealTargetKind { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct AnnealTargetName { - /// The Cargo package that owns this artifact. - pub package_name: cargo_metadata::PackageName, - /// The Cargo target name. + pub package_name: PackageName, pub target_name: String, - /// The target kind compiled for this artifact. - /// - /// This is part of the identity because one Cargo target can expose - /// multiple crate types, and because later Charon and Lean outputs must not - /// rely on target names alone. pub kind: AnnealTargetKind, } @@ -149,32 +147,34 @@ pub struct AnnealTargetName { pub struct AnnealTarget { pub name: AnnealTargetName, pub kind: AnnealTargetKind, - + /// Path to the main source file for this target. + pub src_path: PathBuf, /// Path to the `Cargo.toml` for this target. - pub manifest_path: std::path::PathBuf, + pub manifest_path: PathBuf, } #[derive(Debug)] pub struct Roots { + pub workspace: PathBuf, // E.g., `target/anneal`. - anneal_global_root: std::path::PathBuf, + anneal_global_root: PathBuf, // E.g., `target/anneal/`. - anneal_run_root: std::path::PathBuf, + anneal_run_root: PathBuf, pub roots: Vec, } impl Roots { - pub fn lock_run_root(&self) -> anyhow::Result> { - let lock = crate::util::DirLock::lock_exclusive(self.anneal_run_root.clone())?; - Ok(LockedRoots { roots: self, anneal_run_root: lock, llbc_override: None }) + pub fn lock_run_root(&self) -> Result> { + let lock = DirLock::lock_exclusive(self.anneal_run_root.clone())?; + Ok(LockedRoots { roots: self, anneal_run_root: lock }) } - pub fn cargo_target_dir(&self) -> std::path::PathBuf { + pub fn cargo_target_dir(&self) -> PathBuf { self.anneal_global_root.join("cargo_target") } } -/// A wrapper around [`crate::resolve::Roots`] that proves the build lock is held. +/// A wrapper around `Roots` that proves the build lock is held. /// /// This struct is the *only* way to access paths within the Anneal build /// directory (e.g., LLBC output, Lean generation). This enforces that all @@ -182,37 +182,38 @@ impl Roots { pub struct LockedRoots<'a> { roots: &'a Roots, anneal_run_root: crate::util::DirLock, - pub llbc_override: Option, } impl<'a> LockedRoots<'a> { - pub fn llbc_root(&self) -> std::path::PathBuf { - if let Some(ref over) = self.llbc_override { - over.clone() - } else { - self.anneal_run_root.path.join("llbc") - } + pub fn llbc_root(&self) -> PathBuf { + self.anneal_run_root.path.join("llbc") + } + + pub fn lean_root(&self) -> PathBuf { + self.anneal_run_root.path.join("lean") + } + + pub fn lean_generated_root(&self) -> PathBuf { + self.lean_root().join("generated") } // We expose the Cargo target directory for convenience, as it is used // by downstream tools like Charon to coordinate dependency artifacts. - pub fn cargo_target_dir(&self) -> std::path::PathBuf { + pub fn cargo_target_dir(&self) -> PathBuf { self.roots.cargo_target_dir() } + + pub fn workspace(&self) -> &PathBuf { + &self.roots.workspace + } } /// Resolves all verification roots. /// /// Each entry represents a distinct compilation artifact to be verified. -/// Keeping this artifact list explicit is deliberate: later Charon invocation -/// code should not have to rediscover which files a Cargo flag happened to -/// produce for a particular workspace shape. -pub fn resolve_roots(args: &Args, toolchain: &crate::setup::Toolchain) -> anyhow::Result { +pub fn resolve_roots(args: &Args) -> Result { log::trace!("resolve_roots({:?})", args); - let mut cmd = cargo_metadata::MetadataCommand::new(); - cmd.cargo_path(crate::setup::Tool::Cargo.path(toolchain)) - .env("RUSTC", crate::setup::Tool::Rustc.path(toolchain)) - .env(crate::setup::rust_library_path_env_var(), toolchain.rust_lib()); + let mut cmd = MetadataCommand::new(); if let Some(path) = &args.manifest.manifest_path { cmd.manifest_path(path); @@ -227,19 +228,18 @@ pub fn resolve_roots(args: &Args, toolchain: &crate::setup::Toolchain) -> anyhow args.features.forward_metadata(&mut cmd); let metadata = cmd.exec().context("Failed to run 'cargo metadata'")?; - // We enforce that all local dependencies are contained within the workspace - // root. This is a temporary limitation to simplify the verification model - // and ensure a "hermetic-like" boundary for analysis. It prevents issues - // where experimental or local forks of dependencies might be picked up - // unpredictably, or where Charon might struggle to locate source files - // outside the standard project structure. - check_for_external_deps(&metadata)?; - let selected_packages = resolve_packages(&metadata, &args.workspace, args.manifest.manifest_path.as_deref())?; + check_selected_packages_in_workspace(&metadata, &selected_packages)?; let (anneal_global_root, anneal_run_root) = resolve_run_roots(&metadata); - let mut roots = Roots { anneal_global_root, anneal_run_root, roots: Vec::new() }; + let mut roots = Roots { + workspace: metadata.workspace_root.as_std_path().to_owned(), + // cargo_target_dir: metadata.target_directory.as_std_path().to_owned(), + anneal_global_root, + anneal_run_root, + roots: Vec::new(), + }; for package in selected_packages { log::trace!("Scanning package: {}", package.name); @@ -262,6 +262,7 @@ pub fn resolve_roots(args: &Args, toolchain: &crate::setup::Toolchain) -> anyhow // reference for the rest of the pipeline. This avoids ambiguity // if the CWD changes or if we're working with complex workspace // structures. + src_path: target.src_path.as_std_path().to_owned(), manifest_path: package.manifest_path.as_std_path().to_owned(), })); } @@ -269,22 +270,26 @@ pub fn resolve_roots(args: &Args, toolchain: &crate::setup::Toolchain) -> anyhow Ok(roots) } -fn resolve_run_roots( - metadata: &cargo_metadata::Metadata, -) -> (std::path::PathBuf, std::path::PathBuf) { +fn resolve_run_roots(metadata: &Metadata) -> (PathBuf, PathBuf) { log::trace!("resolve_run_root"); log::debug!("workspace_root: {:?}", metadata.workspace_root.as_std_path()); // NOTE: Automatically handles `CARGO_TARGET_DIR` env var. let target_dir = metadata.target_directory.as_std_path(); let anneal_global = target_dir.join("anneal"); + // Used by integration tests to ensure deterministic shadow dir names. + if let Ok(name) = std::env::var("ANNEAL_TEST_DIR_NAME") { + let run_root = anneal_global.join(name); + return (anneal_global, run_root); + } + // Hash the path to the workspace root to avoid collisions between different // workspaces using the same target directory. We use SHA-256 (truncated to // 64 bits) for stable hashing across Rust versions. This ensures that the // build directory name remains consistent for the same workspace root, // avoiding unnecessary cache invalidation. let workspace_root_hash = { - let mut hasher = sha2::Sha256::new(); + let mut hasher = Sha256::new(); hasher.update(b"anneal_build_salt"); hasher.update(metadata.workspace_root.as_str().as_bytes()); let result = hasher.finalize(); @@ -299,13 +304,13 @@ fn resolve_run_roots( /// Resolves which packages to process based on workspace flags and CWD. fn resolve_packages<'a>( - metadata: &'a cargo_metadata::Metadata, + metadata: &'a Metadata, args: &clap_cargo::Workspace, manifest_path: Option<&std::path::Path>, -) -> anyhow::Result> { +) -> Result> { log::trace!("resolve_packages(workspace: {}, all: {})", args.workspace, args.all); let mut packages = if !args.package.is_empty() { - // Resolve explicitly selected packages (-p / --package). + // Resolve explicitly selected packages (-p / --package) args.package .iter() .map(|name| { @@ -313,9 +318,9 @@ fn resolve_packages<'a>( .packages .iter() .find(|p| p.name == *name) - .ok_or_else(|| anyhow::anyhow!("Package '{}' not found in workspace", name)) + .ok_or_else(|| anyhow!("Package '{}' not found in workspace", name)) }) - .collect::>>()? + .collect::>>()? } else if args.workspace || args.all { // Resolve entire workspace (--workspace / --all). This explicitly // selects all workspace members, ignoring any packages that might be @@ -332,7 +337,7 @@ fn resolve_packages<'a>( let cwd = { let cwd_candidate = manifest_path .map(|p| p.to_path_buf()) - .unwrap_or_else(|| std::env::current_dir().unwrap_or_default()) + .unwrap_or_else(|| env::current_dir().unwrap_or_default()) .canonicalize() .context("Failed to canonicalize CWD")?; @@ -345,7 +350,7 @@ fn resolve_packages<'a>( } }; - // Find the package whose manifest directory is an ancestor of CWD. + // Find the package whose manifest directory is an ancestor of CWD let current_pkg = metadata.packages.iter().find(|p| { let manifest_dir = p.manifest_path.parent().unwrap(); cwd.starts_with(manifest_dir) @@ -363,14 +368,14 @@ fn resolve_packages<'a>( .filter_map(|id| metadata.packages.iter().find(|p| &p.id == id)) .collect() } else { - return Err(anyhow::anyhow!( + return Err(anyhow!( "Could not determine package from current directory. Please use -p or --workspace." )); } } }; - // Filter out excluded packages (--exclude). + // Filter out excluded packages (--exclude) if !args.exclude.is_empty() { packages.retain(|p| !args.exclude.contains(&p.name)); } @@ -378,9 +383,8 @@ fn resolve_packages<'a>( Ok(packages) } -/// Resolves the Cargo targets selected from one package. -/// -/// Returns a list of `(Target, TargetKind)` pairs. +/// Flattening Resolver: +/// Returns a list of (Target, TargetKind) pairs. /// If a target is defined as `crate-type = ["rlib", "cdylib"]`, and both are /// requested, this returns two entries, allowing them to be verified /// independently. @@ -388,12 +392,12 @@ fn resolve_packages<'a>( /// This flattening is critical because different crate types may be compiled /// with different flags or conditional compilation options (although the /// current scanner is CFG-agnostic, future improvements might respect this). -/// Verifying them independently gives later stages a separate artifact identity -/// and output path for every intended compilation mode. +/// Verifying them independently ensures we cover all intended compilation +/// modes. fn resolve_targets<'a>( - package: &'a cargo_metadata::Package, + package: &'a Package, args: &Args, -) -> anyhow::Result> { +) -> Result> { log::trace!("resolve_targets({})", package.name); let default_mode = !args.lib && args.bin.is_empty() @@ -435,36 +439,38 @@ fn resolve_targets<'a>( Ok(selected_artifacts) } -/// Scans the package graph to ensure all local dependencies are contained -/// within the workspace root. Returns an error if an external path dependency -/// is found. -pub fn check_for_external_deps(metadata: &cargo_metadata::Metadata) -> anyhow::Result<()> { - log::trace!("check_for_external_deps"); - // Canonicalize workspace root to handle symlinks correctly. - let workspace_root = std::fs::canonicalize(&metadata.workspace_root) +// TODO: Eventually, we'll want to support selected packages outside the Cargo +// workspace root by analyzing them in-place or teaching downstream stages how +// to map those source files. + +/// Ensures every selected verification root is contained within the workspace root. +fn check_selected_packages_in_workspace(metadata: &Metadata, packages: &[&Package]) -> Result<()> { + log::trace!("check_selected_packages_in_workspace"); + // Canonicalize workspace root to handle symlinks correctly + let workspace_root = fs::canonicalize(&metadata.workspace_root) .context("Failed to canonicalize workspace root")?; - for pkg in &metadata.packages { - // We only care about packages that are "local" (source is None). - // If source is Some(...), it's from crates.io or git, which is fine - // (handled by Cargo). - if pkg.source.is_none() { - let pkg_path = pkg.manifest_path.as_std_path(); - - // Canonicalize the package path for comparison. - let canonical_pkg_path = std::fs::canonicalize(pkg_path) - .with_context(|| format!("Failed to canonicalize path for package {}", pkg.name))?; - - // Check if the package lives outside the workspace tree. - if !canonical_pkg_path.starts_with(&workspace_root) { - anyhow::bail!( - "Unsupported external dependency: '{}' at {:?}.\n\ - Anneal currently only supports verifying workspaces where all local \ - dependencies are contained within the workspace root.", - pkg.name, - pkg_path - ); - } + for pkg in packages { + let pkg_path = pkg.manifest_path.as_std_path(); + + // Canonicalize the package path for comparison + let canonical_pkg_path = fs::canonicalize(pkg_path) + .with_context(|| format!("Failed to canonicalize path for package {}", pkg.name))?; + + // We only constrain the packages Anneal will scan as verification + // roots. Cargo metadata may also include build-only local path + // dependencies from the Anneal implementation itself, such as the + // repository-root `exocrate` helper crate when running + // `cargo run verify`. Rejecting those would make Anneal's own package + // layout constrain user verification. + if !canonical_pkg_path.starts_with(&workspace_root) { + anyhow::bail!( + "Unsupported external package: '{}' at {:?}.\n\ + Anneal currently only supports verifying packages contained \ + within the workspace root.", + pkg.name, + pkg_path + ); } } diff --git a/anneal/v1/src/scanner.rs b/anneal/v1/src/scanner.rs new file mode 100644 index 0000000000..44b66417a8 --- /dev/null +++ b/anneal/v1/src/scanner.rs @@ -0,0 +1,504 @@ +use std::{ + collections::{HashMap, HashSet}, + ffi::OsStr, + path::{Path, PathBuf}, + sync::mpsc::{self, Sender}, +}; + +use anyhow::Result; +use sha2::{Digest as _, Sha256}; + +use crate::{ + parse::{self, ParsedLeanItem}, + resolve::{AnnealTargetKind, AnnealTargetName, LockedRoots, Roots}, +}; + +#[derive(Clone)] +struct ScannerContext { + err_tx: Sender, + // `ParsedLeanItem`s must have their `module_path` field updated to be + // relative to the crate root. + item_tx: Sender<(AnnealTargetName, ParsedLeanItem, String)>, + name: AnnealTargetName, + current_prefix: Vec, +} + +/// A scanned artifact containing all the necessary information to generate +/// a Lean specification. +/// +/// This represents a single Rust target (library, binary, etc.) and includes +/// the list of discovered Anneal items and the calculated entry points for +/// Charon. +pub struct AnnealArtifact { + pub name: AnnealTargetName, + pub target_kind: AnnealTargetKind, + /// The path to the crate's `Cargo.toml`. + pub manifest_path: PathBuf, + pub items: Vec>, + // NOTE: We store `start_from` as a `HashSet` rather than a `Vec` as an + // optimization: when we encounter items which we can't name (which carry + // Anneal annotations), we add their parent module to the list of + // entrypoints. If there are multiple items in the same module, this can + // lead to duplication in the list of entrypoints. Storing them in a + // `HashSet` avoids us having to de-dup later. + pub start_from: HashSet, +} + +impl AnnealArtifact { + /// Returns a unique, Lean-compatible "slug" for this artifact that matches + /// the name that Aeneas will expect for the corresponding Lean module. + /// + /// Guarantees uniqueness based on manifest path even if multiple packages + /// have the same name. The slug is guaranteed to be a valid Lean + /// identifier (no hyphens). + pub fn artifact_slug(&self) -> String { + fn hash(data: &[u8]) -> u64 { + let mut hasher = Sha256::new(); + hasher.update(data); + let result = hasher.finalize(); + let mut bytes = [0u8; 8]; + bytes.copy_from_slice(&result[0..8]); + u64::from_le_bytes(bytes) + } + + // Double-hash to make sure we can distinguish between e.g. + // (manifest_path, target_name) = ("abc", "def") and ("ab", "cdef"), + // which would hash identically if we just hashed their concatenation. + // + // Use SHA-256 not for security but rather stability – Rust's + // `DefaultHasher` doesn't guarantee stability even across runs of the + // same binary. + // + // `ANNEAL_HASH_WITH_REMOVED_PREFIX` allows our integration test + // framework to strip the randomized sandbox prefix from the manifest + // path before hashing, ensuring deterministic hashes even when running + // in a sandboxed environment. + let mut manifest_path_to_hash = self.manifest_path.as_path(); + if let Ok(prefix) = std::env::var("ANNEAL_HASH_WITH_REMOVED_PREFIX") { + if let Ok(stripped) = self.manifest_path.strip_prefix(&prefix) { + manifest_path_to_hash = stripped; + } + } + let h0 = hash(manifest_path_to_hash.as_os_str().as_encoded_bytes()); + let h1 = hash(self.name.target_name.as_bytes()); + let h2 = hash(&[self.target_kind as u8]); + let hashes = [h0, h1, h2]; + let h = hash(&hashes.map(u64::to_ne_bytes).concat()); + + // Converts kebab-case -> PascalCase. + // We convert both package and target names to PascalCase to ensure + // the generated Lean module name is a valid and idiomatic Lean + // identifier, matching Aeneas's output format. + let to_pascal = |s: &str| { + s.split(['-', '_']) + .map(|segment| { + let mut chars = segment.chars(); + match chars.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + chars.as_str(), + } + }) + .collect::() + }; + + let pkg = to_pascal(self.name.package_name.as_str()); + let target = to_pascal(&self.name.target_name); + + // We use the hash to ensure uniqueness. + format!("{}{}{:08x}", pkg, target, h) + } + + /// Returns the name of the `.llbc` file to use for this artifact. + pub fn llbc_file_name(&self) -> String { + format!("{}.llbc", self.artifact_slug()) + } + + /// Returns the name of the `.lean` spec file to use for this artifact. + pub fn lean_spec_file_name(&self) -> String { + format!("{}.lean", self.artifact_slug()) + } + + /// Returns the absolute path to the .llbc file. + /// + /// This method requires `LockedRoots` to ensure that the caller holds the + /// build lock before accessing the build artifact path. + pub fn llbc_path(&self, roots: &LockedRoots) -> PathBuf { + roots.llbc_root().join(self.llbc_file_name()) + } + + /// Returns true if this artifact contains items that should result in a `Funs.lean` file. + pub fn has_functions(&self) -> bool { + self.items.iter().any(|i| { + matches!( + i.item, + crate::parse::ParsedItem::Function(_) | crate::parse::ParsedItem::Impl(_) + ) + }) + } + + /// Returns true if this artifact contains items that should result in a `Types.lean` file. + pub fn has_types(&self) -> bool { + self.items.iter().any(|i| { + matches!(i.item, crate::parse::ParsedItem::Type(_) | crate::parse::ParsedItem::Trait(_)) + }) + } +} + +/// Scans the workspace to identify Anneal entry points (`/// ```lean` blocks) +/// and collects targets for verification. +pub fn scan_workspace(roots: &Roots) -> Result> { + log::trace!("scan_workspace({:?})", roots); + + let (err_tx, err_rx) = mpsc::channel::(); + let (item_tx, item_rx) = + mpsc::channel::<(AnnealTargetName, ParsedLeanItem, String)>(); + + let monitor_handle = std::thread::spawn(move || { + let mut error_count = 0; + for err in err_rx { + if error_count == 0 { + eprintln!("\n=== Anneal Verification Failed ==="); + } + error_count += 1; + // Use eprintln! to print immediately to stderr + // `miette::Report` natively formats with rich diagnostic spans via `{:?}`. + eprintln!("\n[Anneal Error] {:?}", err); + } + error_count + }); + + rayon::scope(|s| { + for target in &roots.roots { + let ctx = ScannerContext { + err_tx: err_tx.clone(), + item_tx: item_tx.clone(), + name: target.name.clone(), + current_prefix: vec!["crate".to_string()], + }; + s.spawn(move |s| { + process_file_recursive( + s, + &target.src_path, + ctx, + false, // Initial call is top-level, so not inside block + Vec::new(), + ) + }); + } + }); + + // Inform the monitor thread that no more errors will be sent, causing it to + // exit. + drop(err_tx); + + let (mut entry_points, mut start_from_map) = { + drop(item_tx); + let mut entry_points = + HashMap::>>::new(); + let mut start_from_map = HashMap::>::new(); + for (target, item, sf_str) in item_rx { + start_from_map.entry(target.clone()).or_default().insert(sf_str); + entry_points.entry(target).or_default().push(item); + } + (entry_points, start_from_map) + }; + + // Wait for the monitor to finish flushing the errors. + let count = monitor_handle.join().expect("Error monitor thread panicked"); + + if count > 0 { + return Err(anyhow::anyhow!("Aborting due to {} previous errors.", count)); + } + + Ok(roots + .roots + .iter() + .filter_map(|target| { + Some(AnnealArtifact { + name: target.name.clone(), + target_kind: target.kind, + manifest_path: target.manifest_path.clone(), + items: entry_points.remove(&target.name)?, + start_from: start_from_map.remove(&target.name).unwrap_or_default(), + }) + }) + .collect()) +} + +// NOTE: It might be tempting to try to deduplicate files to avoid re-processing +// a file that is reachable via multiple paths. However, this is incorrect, as +// this only happens if the file is named in multiple `#[path]` attributes, in +// which case it logically constitutes a distinct module each time it is +// referenced. +fn process_file_recursive<'a>( + scope: &rayon::Scope<'a>, + src_path: &Path, + ctx: ScannerContext, + inside_block: bool, + mut ancestors: Vec, +) { + log::trace!("process_file_recursive(src_path: {:?})", src_path); + + // Canonicalize the path to ensure we don't process the same file multiple + // times (e.g. via symlinks or different relative paths). + let src_path = match std::fs::canonicalize(src_path) { + Ok(p) => p, + Err(e) => { + // It is valid for a module to be declared but not exist (e.g., if + // it is cfg-gated for another platform). In strict Rust, we would + // check the cfg attributes, but since we are just scanning, it is + // safe to warn and return. + // + // Note: The scanner is currently CFG-agnostic. It does not evaluate + // `#[cfg(...)]` attributes, so it may attempt to scan files that + // are disabled for the current target (e.g., Windows-specific code + // on Linux). This is a known limitation that may cause build failures + // in Charon if it tries to verify non-existent items. + log::debug!("Skipping unreachable or missing file {:?}: {}", src_path, e); + return; + } + }; + + // Cycle detection: prevent infinite recursion on symlinks or recursive mod + // declarations, while still allowing identical files to be mounted in + // different branches of the tree. A cycle would represent an invalid crate + // anyway (i.e., an invalid set of `#[path]` attributes). + // + // Note: This check is purely path-based. It does not inspect the content of + // the file. + if ancestors.contains(&src_path) { + return; + } + ancestors.push(src_path.clone()); + + let result = parse::read_file_and_scan_compilation_unit( + &src_path, + inside_block, + |_src, res| match res { + Ok(mut item) => { + item.module_path.splice(0..0, ctx.current_prefix.clone()); + + let unreliable = match &item.item { + crate::parse::ParsedItem::Impl(_) => true, + crate::parse::ParsedItem::Function(f) => { + matches!( + f.item, + crate::parse::FunctionItem::Impl(..) + | crate::parse::FunctionItem::Trait(_) + | crate::parse::FunctionItem::Foreign(_) + ) + } + _ => false, + }; + let module_path = item.module_path.join("::"); + let start_from_str = if unreliable { + // For items where we cannot reliably determine the fully qualified + // name (e.g., items inside `impl` blocks or `trait` definitions), + // we must fall back to using the containing module as the + // entry point. This forces Charon to analyze the entire module, + // which is less efficient but ensures we don't miss the item. + module_path + } else { + format!("{}::{}", module_path, item.item.name().unwrap()) + }; + + use crate::parse::hkd::LiftToSafe; + // Before sending the parsed item across the thread boundary + // (from the `rayon` worker back to the main thread), we must + // "lift" the AST nodes. This internally drops the rich, + // non-`Send` `syn` trees stored in the `Local` mode, + // transforming them into the lightweight, `Send`-safe `Safe` + // equivalents (e.g., `SafeType` and `SafeSignature`). + ctx.item_tx.send((ctx.name.clone(), item.lift(), start_from_str)).unwrap(); + } + Err(e) => { + let _ = ctx.err_tx.send(miette::Report::new(e)); + } + }, + ); + + // After scanning the current file, we look for declared submodules that + // were not loaded inline (i.e., `mod foo;` instead of `mod foo { ... }`). + // `read_file_and_scan_compilation_unit` returns a list of these "unloaded" + // modules so we can resolve their paths and recurse. + let (_, unloaded_modules) = match result { + Ok(res) => res, + Err(e) => { + let _ = ctx.err_tx.send(miette::miette!("{:#}", e)); + return; + } + }; + + // Determine the directory to search for child modules in. + // - For `mod.rs`, `lib.rs`, `main.rs`, children are in the parent directory. + // e.g. `src/lib.rs` -> `mod foo` -> `src/foo.rs` + // - For `my_mod.rs`, children are in a sibling directory of the same name. + // e.g. `src/my_mod.rs` -> `mod sub` -> `src/my_mod/sub.rs` + let file_stem = src_path.file_stem().and_then(OsStr::to_str).unwrap_or(""); + let base_dir = if matches!(file_stem, "mod" | "lib" | "main") { + // If we are in `mod.rs`, `lib.rs`, or `main.rs`, then `mod foo;` + // looks for `foo.rs` or `foo/mod.rs` in the *same* directory. + // + // e.g. `src/lib.rs` -> `mod foo` -> `src/foo.rs` + src_path.parent().unwrap_or(&src_path).to_path_buf() + } else { + // If we are in `src/foo.rs`, then `mod bar;` looks for + // `src/foo/bar.rs` or `src/foo/bar/mod.rs`. + // + // e.g. src/foo.rs -> src/foo/ + src_path.with_extension("") + }; + + // Resolve and queue child modules for processing. + for module in unloaded_modules { + if let Some(mod_path) = + resolve_module_path(&base_dir, &module.name, module.path_attr.as_deref()) + { + // Spawn new tasks for discovered modules. + let mut ctx_clone = ctx.clone(); + ctx_clone.current_prefix.push(module.name); + + // TODO: Can we do something more efficient than cloning here? Maybe + // a linked list? + let ancestors = ancestors.clone(); + scope.spawn(move |s| { + process_file_recursive(s, &mod_path, ctx_clone, module.inside_block, ancestors) + }) + } else { + // This is an expected condition – it shows up when modules are + // conditionally compiled. Instead of implementing conditional + // compilation ourselves, we can just let rustc error later if + // this is actually an error. + // + // Example: `#[cfg(windows)] mod win_only;` on Linux. `win_only.rs` + // might not exist at all, or might verify successfully but be + // ignored by rustc. We just skip it here. + log::debug!("Could not resolve module '{}' in {:?}", module.name, src_path); + } + } +} + +/// Resolves a module name to a file path, checking standard Rust locations. +/// +/// * `base_dir`: The directory containing the parent file. +/// * `mod_name`: The name of the module (e.g., "foo"). +/// * `path_attr`: The optional `#[path = "..."]` attribute string. +fn resolve_module_path( + base_dir: &Path, + mod_name: &str, + path_attr: Option<&str>, +) -> Option { + log::trace!( + "resolve_module_path(base_dir: {:?}, mod_name: {:?}, path_attr: {:?})", + base_dir, + mod_name, + path_attr + ); + + // If `#[path = "..."]` is present, it overrides the standard lookup logic. + // The path is always relative to the current module's directory. + if let Some(custom_path) = path_attr { + let p = base_dir.join(custom_path); + if p.exists() { + return Some(p); + } + return None; + } + + // Standard lookup: `foo.rs` + let inline = base_dir.join(format!("{}.rs", mod_name)); + if inline.exists() { + return Some(inline); + } + + // Standard lookup: `foo/mod.rs` + let nested = base_dir.join(mod_name).join("mod.rs"); + if nested.exists() { + return Some(nested); + } + + None +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use cargo_metadata::PackageName; + + use super::*; + use crate::resolve::{AnnealTargetKind, AnnealTargetName}; + + #[test] + fn test_llbc_file_name_collision() { + let name_lib = AnnealTargetName { + package_name: PackageName::new("pkg".to_string()), + target_name: "name".to_string(), + kind: AnnealTargetKind::Lib, + }; + + let artifact_lib = AnnealArtifact { + name: name_lib.clone(), + target_kind: AnnealTargetKind::Lib, + manifest_path: PathBuf::from("Cargo.toml"), + start_from: std::collections::HashSet::new(), + items: vec![], + }; + + let name_bin = AnnealTargetName { + package_name: PackageName::new("pkg".to_string()), + target_name: "name".to_string(), + kind: AnnealTargetKind::Bin, + }; + + let artifact_bin = AnnealArtifact { + name: name_bin, + target_kind: AnnealTargetKind::Bin, + manifest_path: PathBuf::from("Cargo.toml"), + start_from: std::collections::HashSet::new(), + items: vec![], + }; + + let artifact_workspace_collision = AnnealArtifact { + name: name_lib.clone(), + target_kind: AnnealTargetKind::Lib, + // A different manifest but identical package/target semantics + manifest_path: PathBuf::from("crates/other/Cargo.toml"), + start_from: std::collections::HashSet::new(), + items: vec![], + }; + + // The file names must be distinct because of the trailing hash. + assert_ne!(artifact_lib.llbc_file_name(), artifact_bin.llbc_file_name()); + assert!(artifact_lib.llbc_file_name().starts_with("PkgName")); + assert!(artifact_bin.llbc_file_name().starts_with("PkgName")); + + // Distinct `manifest_path`s must prevent collisions even when the + // package name and target semantics are otherwise identical. + assert_ne!(artifact_lib.llbc_file_name(), artifact_workspace_collision.llbc_file_name()); + assert!(artifact_workspace_collision.llbc_file_name().starts_with("PkgName")); + } + + #[test] + fn test_lean_spec_file_name_uses_slug() { + let name = AnnealTargetName { + package_name: PackageName::new("pkg-foo".to_string()), + target_name: "name-bar".to_string(), + kind: AnnealTargetKind::Lib, + }; + + let artifact = AnnealArtifact { + name, + target_kind: AnnealTargetKind::Lib, + manifest_path: PathBuf::from("Cargo.toml"), + start_from: std::collections::HashSet::new(), + items: vec![], + }; + + // Slug should be PascalCase: PkgFoo_NameBar_ + // Spec file should be slug + .lean + let spec_name = artifact.lean_spec_file_name(); + assert!(spec_name.starts_with("PkgFooNameBar")); + assert!(spec_name.ends_with(".lean")); + } +} diff --git a/anneal/v1/src/setup.rs b/anneal/v1/src/setup.rs new file mode 100644 index 0000000000..b6d25ade59 --- /dev/null +++ b/anneal/v1/src/setup.rs @@ -0,0 +1,213 @@ +//! Subcommand for installing Anneal dependencies. + +use std::{path::PathBuf, process::Command}; + +use anyhow::Context as _; + +pub struct SetupArgs { + pub local_archive: Option, +} + +pub const CONFIG: exocrate::Config = exocrate::Config { + rel_dir_path: &["anneal", "toolchain"], + version_slug: env!("ANNEAL_EXOCRATE_VERSION_SLUG"), +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Tool { + Charon, + #[allow(dead_code)] + CharonDriver, + Aeneas, +} + +impl Tool { + pub fn name(&self) -> &'static str { + match self { + Self::Charon => "charon", + Self::CharonDriver => "charon-driver", + Self::Aeneas => "aeneas", + } + } + + pub fn path(&self, toolchain: &Toolchain) -> PathBuf { + match self { + Self::Charon | Self::CharonDriver | Self::Aeneas => { + toolchain.aeneas_bin_dir().join(self.name()) + } + } + } +} + +const AENEAS_DIR: &str = "aeneas"; +const AENEAS_BACKENDS_DIR: &str = "backends"; +const AENEAS_LEAN_DIR: &str = "lean"; +const BIN_DIR: &str = "bin"; +const LIB_DIR: &str = "lib"; +const LEAN_SYSROOT: &str = "lean"; +const RUST_SYSROOT: &str = "rust"; + +pub struct Toolchain { + pub root: PathBuf, +} + +impl Toolchain { + pub fn resolve() -> anyhow::Result { + let root = CONFIG + .resolve_installation_dir(location()) + .context("Toolchain not installed. Please run 'cargo anneal setup' first.")?; + Ok(Self { root }) + } + + pub fn bin_dir(&self) -> PathBuf { + self.aeneas_bin_dir() + } + + pub fn cache_dir(&self) -> PathBuf { + self.root.join("lake-cache") + } + + pub fn aeneas_root(&self) -> PathBuf { + self.root.join(AENEAS_DIR) + } + + pub fn aeneas_bin_dir(&self) -> PathBuf { + self.aeneas_root().join(BIN_DIR) + } + + pub fn aeneas_lean_dir(&self) -> PathBuf { + self.aeneas_root().join(AENEAS_BACKENDS_DIR).join(AENEAS_LEAN_DIR) + } + + pub fn rust_sysroot(&self) -> PathBuf { + self.root.join(RUST_SYSROOT) + } + + pub fn rust_bin(&self) -> PathBuf { + self.rust_sysroot().join(BIN_DIR) + } + + pub fn rust_lib(&self) -> PathBuf { + self.rust_sysroot().join(LIB_DIR) + } + + pub fn lean_sysroot(&self) -> PathBuf { + self.root.join(LEAN_SYSROOT) + } + + pub fn lean_bin(&self) -> PathBuf { + self.lean_sysroot().join(BIN_DIR) + } + + pub fn command(&self, tool: Tool) -> Command { + if std::env::var("ANNEAL_USE_PATH_FOR_TOOLS").is_ok() { + Command::new(tool.name()) + } else { + Command::new(tool.path(self)) + } + } +} + +pub fn run_setup(args: SetupArgs) -> anyhow::Result<()> { + let local_archive = args + .local_archive + .or_else(|| std::env::var_os("ANNEAL_SETUP_LOCAL_ARCHIVE").map(PathBuf::from)); + let source = match local_archive { + Some(local_archive) => exocrate::Source::Local(local_archive), + None => exocrate::Source::Remote(remote_archive()), + }; + + let installation_dir = CONFIG + .resolve_installation_dir_or_install(location(), source) + .context("failed to resolve-or-install dependencies")?; + log::info!("anneal toolchain is installed at {:?}", installation_dir); + Ok(()) +} + +fn location() -> exocrate::Location { + if let Some(dir) = std::env::var_os("ANNEAL_TOOLCHAIN_DIR") { + exocrate::Location::Custom(PathBuf::from(dir)) + } else if std::env::var("__ZEROCOPY_LOCAL_DEV").is_ok() + || std::env::var("__ANNEAL_LOCAL_DEV").is_ok() + { + exocrate::Location::LocalDev + } else { + exocrate::Location::UserGlobal + } +} + +fn remote_archive() -> exocrate::RemoteArchive { + match (std::env::consts::OS, std::env::consts::ARCH) { + ("linux", "x86_64") => remote_archive_for( + env!("ANNEAL_EXOCRATE_LINUX_X86_64_URL"), + env!("ANNEAL_EXOCRATE_LINUX_X86_64_SHA256"), + ), + ("macos", "x86_64") => remote_archive_for( + env!("ANNEAL_EXOCRATE_MACOS_X86_64_URL"), + env!("ANNEAL_EXOCRATE_MACOS_X86_64_SHA256"), + ), + ("linux", "aarch64") => remote_archive_for( + env!("ANNEAL_EXOCRATE_LINUX_AARCH64_URL"), + env!("ANNEAL_EXOCRATE_LINUX_AARCH64_SHA256"), + ), + ("macos", "aarch64") => remote_archive_for( + env!("ANNEAL_EXOCRATE_MACOS_AARCH64_URL"), + env!("ANNEAL_EXOCRATE_MACOS_AARCH64_SHA256"), + ), + (os, arch) => panic!("unsupported platform: {os}-{arch}"), + } +} + +fn remote_archive_for(url: &'static str, sha256: &'static str) -> exocrate::RemoteArchive { + exocrate::RemoteArchive { + url, + sha256: decode_hex(sha256).expect("package.metadata.exocrate sha256 must be valid hex"), + } +} + +fn decode_hex(s: &str) -> Option<[u8; 32]> { + let bytes = s.as_bytes(); + if bytes.len() != 64 { + return None; + } + let mut res = [0u8; 32]; + for i in 0..32 { + let h_nib = decode_nibble(bytes[i * 2])?; + let l_nib = decode_nibble(bytes[i * 2 + 1])?; + res[i] = (h_nib << 4) | l_nib; + } + Some(res) +} + +fn decode_nibble(c: u8) -> Option { + match c { + b'0'..=b'9' => Some(c - b'0'), + b'a'..=b'f' => Some(c - b'a' + 10), + b'A'..=b'F' => Some(c - b'A' + 10), + _ => None, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tool_paths_use_omnibus_layout() { + let toolchain = Toolchain { root: PathBuf::from("/tmp/toolchain") }; + + assert_eq!(toolchain.bin_dir(), PathBuf::from("/tmp/toolchain/aeneas/bin")); + assert_eq!( + toolchain.aeneas_lean_dir(), + PathBuf::from("/tmp/toolchain/aeneas/backends/lean") + ); + assert_eq!( + Tool::Charon.path(&toolchain), + PathBuf::from("/tmp/toolchain/aeneas/bin/charon") + ); + assert_eq!( + Tool::Aeneas.path(&toolchain), + PathBuf::from("/tmp/toolchain/aeneas/bin/aeneas") + ); + } +} diff --git a/anneal/src/ui_test_shim.rs b/anneal/v1/src/ui_test_shim.rs similarity index 100% rename from anneal/src/ui_test_shim.rs rename to anneal/v1/src/ui_test_shim.rs diff --git a/anneal/v1/src/util.rs b/anneal/v1/src/util.rs new file mode 100644 index 0000000000..fe085b37dc --- /dev/null +++ b/anneal/v1/src/util.rs @@ -0,0 +1,59 @@ +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use fs2::FileExt; + +/// Represents an active, exclusive lock on a directory. +/// +/// This struct guarantees that the process holds an OS-level file lock +/// guarding the specified directory. +pub struct DirLock { + /// The path to the directory being guarded. + pub path: PathBuf, + // Kept alive to hold the flock + _file: std::fs::File, +} + +impl DirLock { + /// Acquires an exclusive lock on the specified directory. + /// + /// This function blocks until the lock can be acquired. We use a + /// separate `.lock` file within the directory rather than locking + /// the directory itself to avoid platform-specific issues with + /// directory locking and to ensure the lock file persists even if + /// the directory is cleaned. + pub fn lock_exclusive(path: PathBuf) -> Result { + let file = Self::open_lock_file(&path)?; + file.lock_exclusive() + .with_context(|| format!("Failed to acquire exclusive lock on {:?}", path))?; + Ok(Self { path, _file: file }) + } + + fn open_lock_file(path: &std::path::Path) -> Result { + let lock_path = path.join(".lock"); + + // Ensure the directory exists + if let Some(parent) = lock_path.parent() { + std::fs::create_dir_all(parent).with_context(|| { + format!("Failed to create directory for lock file: {:?}", parent) + })?; + } + // If the lock file already exists, we open it in read-only mode. + // This prevents failures if the file is read-only (e.g., after + // making the toolchain directory read-only), while still allowing + // us to acquire shared and exclusive locks on the file descriptor. + if lock_path.exists() { + std::fs::OpenOptions::new() + .read(true) + .open(&lock_path) + .with_context(|| format!("Failed to open lock file at {:?}", lock_path)) + } else { + std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&lock_path) + .with_context(|| format!("Failed to create lock file at {:?}", lock_path)) + } + } +} diff --git a/anneal/src/validate.rs b/anneal/v1/src/validate.rs similarity index 100% rename from anneal/src/validate.rs rename to anneal/v1/src/validate.rs diff --git a/anneal/testdata/setup/aeneas-linux-aarch64.tar.gz b/anneal/v1/testdata/setup/aeneas-linux-aarch64.tar.gz similarity index 100% rename from anneal/testdata/setup/aeneas-linux-aarch64.tar.gz rename to anneal/v1/testdata/setup/aeneas-linux-aarch64.tar.gz diff --git a/anneal/testdata/setup/aeneas-linux-x86_64.tar.gz b/anneal/v1/testdata/setup/aeneas-linux-x86_64.tar.gz similarity index 100% rename from anneal/testdata/setup/aeneas-linux-x86_64.tar.gz rename to anneal/v1/testdata/setup/aeneas-linux-x86_64.tar.gz diff --git a/anneal/testdata/setup/aeneas-macos-aarch64.tar.gz b/anneal/v1/testdata/setup/aeneas-macos-aarch64.tar.gz similarity index 100% rename from anneal/testdata/setup/aeneas-macos-aarch64.tar.gz rename to anneal/v1/testdata/setup/aeneas-macos-aarch64.tar.gz diff --git a/anneal/testdata/setup/aeneas-macos-x86_64.tar.gz b/anneal/v1/testdata/setup/aeneas-macos-x86_64.tar.gz similarity index 100% rename from anneal/testdata/setup/aeneas-macos-x86_64.tar.gz rename to anneal/v1/testdata/setup/aeneas-macos-x86_64.tar.gz diff --git a/anneal/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.gz b/anneal/v1/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.gz similarity index 100% rename from anneal/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.gz rename to anneal/v1/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.gz diff --git a/anneal/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz b/anneal/v1/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz similarity index 100% rename from anneal/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz rename to anneal/v1/testdata/setup/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz diff --git a/anneal/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.gz b/anneal/v1/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.gz similarity index 100% rename from anneal/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.gz rename to anneal/v1/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.gz diff --git a/anneal/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.xz b/anneal/v1/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.xz similarity index 100% rename from anneal/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.xz rename to anneal/v1/testdata/setup/miri-nightly-x86_64-unknown-linux-gnu.tar.xz diff --git a/anneal/testdata/setup/rust-src-nightly.tar.gz b/anneal/v1/testdata/setup/rust-src-nightly.tar.gz similarity index 100% rename from anneal/testdata/setup/rust-src-nightly.tar.gz rename to anneal/v1/testdata/setup/rust-src-nightly.tar.gz diff --git a/anneal/testdata/setup/rust-src-nightly.tar.xz b/anneal/v1/testdata/setup/rust-src-nightly.tar.xz similarity index 100% rename from anneal/testdata/setup/rust-src-nightly.tar.xz rename to anneal/v1/testdata/setup/rust-src-nightly.tar.xz diff --git a/anneal/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz b/anneal/v1/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz similarity index 100% rename from anneal/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz rename to anneal/v1/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.gz diff --git a/anneal/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz b/anneal/v1/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz similarity index 100% rename from anneal/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz rename to anneal/v1/testdata/setup/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz diff --git a/anneal/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.gz b/anneal/v1/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.gz similarity index 100% rename from anneal/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.gz rename to anneal/v1/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.gz diff --git a/anneal/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.xz b/anneal/v1/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.xz similarity index 100% rename from anneal/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.xz rename to anneal/v1/testdata/setup/rustc-dev-nightly-x86_64-unknown-linux-gnu.tar.xz diff --git a/anneal/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz b/anneal/v1/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz similarity index 100% rename from anneal/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz rename to anneal/v1/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz diff --git a/anneal/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz b/anneal/v1/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz similarity index 100% rename from anneal/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz rename to anneal/v1/testdata/setup/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz diff --git a/anneal/tests/.gitignore b/anneal/v1/tests/.gitignore similarity index 100% rename from anneal/tests/.gitignore rename to anneal/v1/tests/.gitignore diff --git a/anneal/tests/fixtures/allow_sorry_fallbacks/anneal.toml b/anneal/v1/tests/fixtures/allow_sorry_fallbacks/anneal.toml similarity index 100% rename from anneal/tests/fixtures/allow_sorry_fallbacks/anneal.toml rename to anneal/v1/tests/fixtures/allow_sorry_fallbacks/anneal.toml diff --git a/anneal/tests/fixtures/allow_sorry_fallbacks/expected.stderr b/anneal/v1/tests/fixtures/allow_sorry_fallbacks/expected.stderr similarity index 100% rename from anneal/tests/fixtures/allow_sorry_fallbacks/expected.stderr rename to anneal/v1/tests/fixtures/allow_sorry_fallbacks/expected.stderr diff --git a/anneal/tests/fixtures/allow_sorry_fallbacks/source/Cargo.toml b/anneal/v1/tests/fixtures/allow_sorry_fallbacks/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/allow_sorry_fallbacks/source/Cargo.toml rename to anneal/v1/tests/fixtures/allow_sorry_fallbacks/source/Cargo.toml diff --git a/anneal/tests/fixtures/allow_sorry_fallbacks/source/src/lib.rs b/anneal/v1/tests/fixtures/allow_sorry_fallbacks/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/allow_sorry_fallbacks/source/src/lib.rs rename to anneal/v1/tests/fixtures/allow_sorry_fallbacks/source/src/lib.rs diff --git a/anneal/tests/fixtures/anneal_multiple_targets/anneal.toml b/anneal/v1/tests/fixtures/anneal_multiple_targets/anneal.toml similarity index 100% rename from anneal/tests/fixtures/anneal_multiple_targets/anneal.toml rename to anneal/v1/tests/fixtures/anneal_multiple_targets/anneal.toml diff --git a/anneal/tests/fixtures/anneal_multiple_targets/source/Cargo.toml b/anneal/v1/tests/fixtures/anneal_multiple_targets/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/anneal_multiple_targets/source/Cargo.toml rename to anneal/v1/tests/fixtures/anneal_multiple_targets/source/Cargo.toml diff --git a/anneal/tests/fixtures/anneal_multiple_targets/source/src/bin/my_bin.rs b/anneal/v1/tests/fixtures/anneal_multiple_targets/source/src/bin/my_bin.rs similarity index 100% rename from anneal/tests/fixtures/anneal_multiple_targets/source/src/bin/my_bin.rs rename to anneal/v1/tests/fixtures/anneal_multiple_targets/source/src/bin/my_bin.rs diff --git a/anneal/tests/fixtures/anneal_multiple_targets/source/src/lib.rs b/anneal/v1/tests/fixtures/anneal_multiple_targets/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/anneal_multiple_targets/source/src/lib.rs rename to anneal/v1/tests/fixtures/anneal_multiple_targets/source/src/lib.rs diff --git a/anneal/tests/fixtures/anneal_shim_syntax_error/anneal.toml b/anneal/v1/tests/fixtures/anneal_shim_syntax_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/anneal_shim_syntax_error/anneal.toml rename to anneal/v1/tests/fixtures/anneal_shim_syntax_error/anneal.toml diff --git a/anneal/tests/fixtures/anneal_shim_syntax_error/expected.stderr b/anneal/v1/tests/fixtures/anneal_shim_syntax_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/anneal_shim_syntax_error/expected.stderr rename to anneal/v1/tests/fixtures/anneal_shim_syntax_error/expected.stderr diff --git a/anneal/tests/fixtures/anneal_shim_syntax_error/mock_charon_output.json b/anneal/v1/tests/fixtures/anneal_shim_syntax_error/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/anneal_shim_syntax_error/mock_charon_output.json rename to anneal/v1/tests/fixtures/anneal_shim_syntax_error/mock_charon_output.json diff --git a/anneal/tests/fixtures/anneal_shim_syntax_error/source/Cargo.toml b/anneal/v1/tests/fixtures/anneal_shim_syntax_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/anneal_shim_syntax_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/anneal_shim_syntax_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/anneal_shim_syntax_error/source/src/lib.rs b/anneal/v1/tests/fixtures/anneal_shim_syntax_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/anneal_shim_syntax_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/anneal_shim_syntax_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/archive_lake_cache_reuse/anneal.toml b/anneal/v1/tests/fixtures/archive_lake_cache_reuse/anneal.toml similarity index 100% rename from anneal/tests/fixtures/archive_lake_cache_reuse/anneal.toml rename to anneal/v1/tests/fixtures/archive_lake_cache_reuse/anneal.toml diff --git a/anneal/tests/fixtures/associated_types/anneal.toml b/anneal/v1/tests/fixtures/associated_types/anneal.toml similarity index 100% rename from anneal/tests/fixtures/associated_types/anneal.toml rename to anneal/v1/tests/fixtures/associated_types/anneal.toml diff --git a/anneal/tests/fixtures/associated_types/expected.stderr b/anneal/v1/tests/fixtures/associated_types/expected.stderr similarity index 100% rename from anneal/tests/fixtures/associated_types/expected.stderr rename to anneal/v1/tests/fixtures/associated_types/expected.stderr diff --git a/anneal/tests/fixtures/associated_types/source/Cargo.toml b/anneal/v1/tests/fixtures/associated_types/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/associated_types/source/Cargo.toml rename to anneal/v1/tests/fixtures/associated_types/source/Cargo.toml diff --git a/anneal/tests/fixtures/associated_types/source/src/lib.rs b/anneal/v1/tests/fixtures/associated_types/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/associated_types/source/src/lib.rs rename to anneal/v1/tests/fixtures/associated_types/source/src/lib.rs diff --git a/anneal/tests/fixtures/broken_doc_block/anneal.toml b/anneal/v1/tests/fixtures/broken_doc_block/anneal.toml similarity index 100% rename from anneal/tests/fixtures/broken_doc_block/anneal.toml rename to anneal/v1/tests/fixtures/broken_doc_block/anneal.toml diff --git a/anneal/tests/fixtures/broken_doc_block/expected.stderr b/anneal/v1/tests/fixtures/broken_doc_block/expected.stderr similarity index 100% rename from anneal/tests/fixtures/broken_doc_block/expected.stderr rename to anneal/v1/tests/fixtures/broken_doc_block/expected.stderr diff --git a/anneal/tests/fixtures/broken_doc_block/source/Cargo.toml b/anneal/v1/tests/fixtures/broken_doc_block/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/broken_doc_block/source/Cargo.toml rename to anneal/v1/tests/fixtures/broken_doc_block/source/Cargo.toml diff --git a/anneal/tests/fixtures/broken_doc_block/source/src/lib.rs b/anneal/v1/tests/fixtures/broken_doc_block/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/broken_doc_block/source/src/lib.rs rename to anneal/v1/tests/fixtures/broken_doc_block/source/src/lib.rs diff --git a/anneal/tests/fixtures/canonicalized_workspace/anneal.toml b/anneal/v1/tests/fixtures/canonicalized_workspace/anneal.toml similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/anneal.toml rename to anneal/v1/tests/fixtures/canonicalized_workspace/anneal.toml diff --git a/anneal/tests/fixtures/canonicalized_workspace/source/Cargo.toml b/anneal/v1/tests/fixtures/canonicalized_workspace/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/source/Cargo.toml rename to anneal/v1/tests/fixtures/canonicalized_workspace/source/Cargo.toml diff --git a/anneal/tests/fixtures/canonicalized_workspace/source/crates/app/Cargo.toml b/anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/source/crates/app/Cargo.toml rename to anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/app/Cargo.toml diff --git a/anneal/tests/fixtures/canonicalized_workspace/source/crates/app/src/lib.rs b/anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/source/crates/app/src/lib.rs rename to anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/app/src/lib.rs diff --git a/anneal/tests/fixtures/canonicalized_workspace/source/crates/lib/Cargo.toml b/anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/lib/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/source/crates/lib/Cargo.toml rename to anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/lib/Cargo.toml diff --git a/anneal/tests/fixtures/canonicalized_workspace/source/crates/lib/src/lib.rs b/anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/lib/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/canonicalized_workspace/source/crates/lib/src/lib.rs rename to anneal/v1/tests/fixtures/canonicalized_workspace/source/crates/lib/src/lib.rs diff --git a/anneal/tests/fixtures/cfg_blind_spot/anneal.toml b/anneal/v1/tests/fixtures/cfg_blind_spot/anneal.toml similarity index 100% rename from anneal/tests/fixtures/cfg_blind_spot/anneal.toml rename to anneal/v1/tests/fixtures/cfg_blind_spot/anneal.toml diff --git a/anneal/tests/fixtures/cfg_blind_spot/expected.stderr b/anneal/v1/tests/fixtures/cfg_blind_spot/expected.stderr similarity index 100% rename from anneal/tests/fixtures/cfg_blind_spot/expected.stderr rename to anneal/v1/tests/fixtures/cfg_blind_spot/expected.stderr diff --git a/anneal/tests/fixtures/cfg_blind_spot/source/Cargo.toml b/anneal/v1/tests/fixtures/cfg_blind_spot/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/cfg_blind_spot/source/Cargo.toml rename to anneal/v1/tests/fixtures/cfg_blind_spot/source/Cargo.toml diff --git a/anneal/tests/fixtures/cfg_blind_spot/source/src/lib.rs b/anneal/v1/tests/fixtures/cfg_blind_spot/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/cfg_blind_spot/source/src/lib.rs rename to anneal/v1/tests/fixtures/cfg_blind_spot/source/src/lib.rs diff --git a/anneal/tests/fixtures/charon_version_match/anneal.toml b/anneal/v1/tests/fixtures/charon_version_match/anneal.toml similarity index 100% rename from anneal/tests/fixtures/charon_version_match/anneal.toml rename to anneal/v1/tests/fixtures/charon_version_match/anneal.toml diff --git a/anneal/tests/fixtures/charon_version_match/expected.stderr b/anneal/v1/tests/fixtures/charon_version_match/expected.stderr similarity index 100% rename from anneal/tests/fixtures/charon_version_match/expected.stderr rename to anneal/v1/tests/fixtures/charon_version_match/expected.stderr diff --git a/anneal/tests/fixtures/charon_version_match/mock_charon.sh b/anneal/v1/tests/fixtures/charon_version_match/mock_charon.sh similarity index 100% rename from anneal/tests/fixtures/charon_version_match/mock_charon.sh rename to anneal/v1/tests/fixtures/charon_version_match/mock_charon.sh diff --git a/anneal/tests/fixtures/charon_version_match/source/Cargo.toml b/anneal/v1/tests/fixtures/charon_version_match/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/charon_version_match/source/Cargo.toml rename to anneal/v1/tests/fixtures/charon_version_match/source/Cargo.toml diff --git a/anneal/tests/fixtures/charon_version_match/source/src/lib.rs b/anneal/v1/tests/fixtures/charon_version_match/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/charon_version_match/source/src/lib.rs rename to anneal/v1/tests/fixtures/charon_version_match/source/src/lib.rs diff --git a/anneal/tests/fixtures/collision/anneal.toml b/anneal/v1/tests/fixtures/collision/anneal.toml similarity index 100% rename from anneal/tests/fixtures/collision/anneal.toml rename to anneal/v1/tests/fixtures/collision/anneal.toml diff --git a/anneal/tests/fixtures/collision/source/Cargo.toml b/anneal/v1/tests/fixtures/collision/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/collision/source/Cargo.toml rename to anneal/v1/tests/fixtures/collision/source/Cargo.toml diff --git a/anneal/tests/fixtures/collision/source/crates/a/Cargo.toml b/anneal/v1/tests/fixtures/collision/source/crates/a/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/collision/source/crates/a/Cargo.toml rename to anneal/v1/tests/fixtures/collision/source/crates/a/Cargo.toml diff --git a/anneal/tests/fixtures/collision/source/crates/a/src/lib.rs b/anneal/v1/tests/fixtures/collision/source/crates/a/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/collision/source/crates/a/src/lib.rs rename to anneal/v1/tests/fixtures/collision/source/crates/a/src/lib.rs diff --git a/anneal/tests/fixtures/collision/source/crates/b/Cargo.toml b/anneal/v1/tests/fixtures/collision/source/crates/b/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/collision/source/crates/b/Cargo.toml rename to anneal/v1/tests/fixtures/collision/source/crates/b/Cargo.toml diff --git a/anneal/tests/fixtures/collision/source/crates/b/src/lib.rs b/anneal/v1/tests/fixtures/collision/source/crates/b/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/collision/source/crates/b/src/lib.rs rename to anneal/v1/tests/fixtures/collision/source/crates/b/src/lib.rs diff --git a/anneal/tests/fixtures/const_block_blind_spot/anneal.toml b/anneal/v1/tests/fixtures/const_block_blind_spot/anneal.toml similarity index 100% rename from anneal/tests/fixtures/const_block_blind_spot/anneal.toml rename to anneal/v1/tests/fixtures/const_block_blind_spot/anneal.toml diff --git a/anneal/tests/fixtures/const_block_blind_spot/expected.stderr b/anneal/v1/tests/fixtures/const_block_blind_spot/expected.stderr similarity index 100% rename from anneal/tests/fixtures/const_block_blind_spot/expected.stderr rename to anneal/v1/tests/fixtures/const_block_blind_spot/expected.stderr diff --git a/anneal/tests/fixtures/const_block_blind_spot/source/Cargo.toml b/anneal/v1/tests/fixtures/const_block_blind_spot/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/const_block_blind_spot/source/Cargo.toml rename to anneal/v1/tests/fixtures/const_block_blind_spot/source/Cargo.toml diff --git a/anneal/tests/fixtures/const_block_blind_spot/source/src/lib.rs b/anneal/v1/tests/fixtures/const_block_blind_spot/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/const_block_blind_spot/source/src/lib.rs rename to anneal/v1/tests/fixtures/const_block_blind_spot/source/src/lib.rs diff --git a/anneal/tests/fixtures/const_generics/anneal.toml b/anneal/v1/tests/fixtures/const_generics/anneal.toml similarity index 100% rename from anneal/tests/fixtures/const_generics/anneal.toml rename to anneal/v1/tests/fixtures/const_generics/anneal.toml diff --git a/anneal/tests/fixtures/const_generics/expected.stderr b/anneal/v1/tests/fixtures/const_generics/expected.stderr similarity index 100% rename from anneal/tests/fixtures/const_generics/expected.stderr rename to anneal/v1/tests/fixtures/const_generics/expected.stderr diff --git a/anneal/tests/fixtures/const_generics/source/Cargo.toml b/anneal/v1/tests/fixtures/const_generics/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/const_generics/source/Cargo.toml rename to anneal/v1/tests/fixtures/const_generics/source/Cargo.toml diff --git a/anneal/tests/fixtures/const_generics/source/src/lib.rs b/anneal/v1/tests/fixtures/const_generics/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/const_generics/source/src/lib.rs rename to anneal/v1/tests/fixtures/const_generics/source/src/lib.rs diff --git a/anneal/tests/fixtures/cyclic_paths/anneal.toml b/anneal/v1/tests/fixtures/cyclic_paths/anneal.toml similarity index 100% rename from anneal/tests/fixtures/cyclic_paths/anneal.toml rename to anneal/v1/tests/fixtures/cyclic_paths/anneal.toml diff --git a/anneal/tests/fixtures/cyclic_paths/expected.stderr b/anneal/v1/tests/fixtures/cyclic_paths/expected.stderr similarity index 100% rename from anneal/tests/fixtures/cyclic_paths/expected.stderr rename to anneal/v1/tests/fixtures/cyclic_paths/expected.stderr diff --git a/anneal/tests/fixtures/cyclic_paths/source/Cargo.toml b/anneal/v1/tests/fixtures/cyclic_paths/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/cyclic_paths/source/Cargo.toml rename to anneal/v1/tests/fixtures/cyclic_paths/source/Cargo.toml diff --git a/anneal/tests/fixtures/cyclic_paths/source/src/lib.rs b/anneal/v1/tests/fixtures/cyclic_paths/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/cyclic_paths/source/src/lib.rs rename to anneal/v1/tests/fixtures/cyclic_paths/source/src/lib.rs diff --git a/anneal/tests/fixtures/diagnostic_mapping/anneal.toml b/anneal/v1/tests/fixtures/diagnostic_mapping/anneal.toml similarity index 100% rename from anneal/tests/fixtures/diagnostic_mapping/anneal.toml rename to anneal/v1/tests/fixtures/diagnostic_mapping/anneal.toml diff --git a/anneal/tests/fixtures/diagnostic_mapping/expected.stderr b/anneal/v1/tests/fixtures/diagnostic_mapping/expected.stderr similarity index 100% rename from anneal/tests/fixtures/diagnostic_mapping/expected.stderr rename to anneal/v1/tests/fixtures/diagnostic_mapping/expected.stderr diff --git a/anneal/tests/fixtures/diagnostic_mapping/source/Cargo.toml b/anneal/v1/tests/fixtures/diagnostic_mapping/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/diagnostic_mapping/source/Cargo.toml rename to anneal/v1/tests/fixtures/diagnostic_mapping/source/Cargo.toml diff --git a/anneal/tests/fixtures/diagnostic_mapping/source/src/lib.rs b/anneal/v1/tests/fixtures/diagnostic_mapping/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/diagnostic_mapping/source/src/lib.rs rename to anneal/v1/tests/fixtures/diagnostic_mapping/source/src/lib.rs diff --git a/anneal/tests/fixtures/dirty_sandbox/anneal.toml b/anneal/v1/tests/fixtures/dirty_sandbox/anneal.toml similarity index 100% rename from anneal/tests/fixtures/dirty_sandbox/anneal.toml rename to anneal/v1/tests/fixtures/dirty_sandbox/anneal.toml diff --git a/anneal/tests/fixtures/dirty_sandbox/source/main.rs b/anneal/v1/tests/fixtures/dirty_sandbox/source/main.rs similarity index 100% rename from anneal/tests/fixtures/dirty_sandbox/source/main.rs rename to anneal/v1/tests/fixtures/dirty_sandbox/source/main.rs diff --git a/anneal/tests/fixtures/dirty_sandbox/source/target/file b/anneal/v1/tests/fixtures/dirty_sandbox/source/target/file similarity index 100% rename from anneal/tests/fixtures/dirty_sandbox/source/target/file rename to anneal/v1/tests/fixtures/dirty_sandbox/source/target/file diff --git a/anneal/tests/fixtures/dst_layout/anneal.toml b/anneal/v1/tests/fixtures/dst_layout/anneal.toml similarity index 100% rename from anneal/tests/fixtures/dst_layout/anneal.toml rename to anneal/v1/tests/fixtures/dst_layout/anneal.toml diff --git a/anneal/tests/fixtures/dst_layout/expected.stderr b/anneal/v1/tests/fixtures/dst_layout/expected.stderr similarity index 100% rename from anneal/tests/fixtures/dst_layout/expected.stderr rename to anneal/v1/tests/fixtures/dst_layout/expected.stderr diff --git a/anneal/tests/fixtures/dst_layout/source/Cargo.toml b/anneal/v1/tests/fixtures/dst_layout/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/dst_layout/source/Cargo.toml rename to anneal/v1/tests/fixtures/dst_layout/source/Cargo.toml diff --git a/anneal/tests/fixtures/dst_layout/source/src/FunsExternal.lean b/anneal/v1/tests/fixtures/dst_layout/source/src/FunsExternal.lean similarity index 100% rename from anneal/tests/fixtures/dst_layout/source/src/FunsExternal.lean rename to anneal/v1/tests/fixtures/dst_layout/source/src/FunsExternal.lean diff --git a/anneal/tests/fixtures/dst_layout/source/src/lib.rs b/anneal/v1/tests/fixtures/dst_layout/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/dst_layout/source/src/lib.rs rename to anneal/v1/tests/fixtures/dst_layout/source/src/lib.rs diff --git a/anneal/tests/fixtures/duplicate_blocks/anneal.toml b/anneal/v1/tests/fixtures/duplicate_blocks/anneal.toml similarity index 100% rename from anneal/tests/fixtures/duplicate_blocks/anneal.toml rename to anneal/v1/tests/fixtures/duplicate_blocks/anneal.toml diff --git a/anneal/tests/fixtures/duplicate_blocks/expected.stderr b/anneal/v1/tests/fixtures/duplicate_blocks/expected.stderr similarity index 100% rename from anneal/tests/fixtures/duplicate_blocks/expected.stderr rename to anneal/v1/tests/fixtures/duplicate_blocks/expected.stderr diff --git a/anneal/tests/fixtures/duplicate_blocks/source/Cargo.toml b/anneal/v1/tests/fixtures/duplicate_blocks/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/duplicate_blocks/source/Cargo.toml rename to anneal/v1/tests/fixtures/duplicate_blocks/source/Cargo.toml diff --git a/anneal/tests/fixtures/duplicate_blocks/source/src/lib.rs b/anneal/v1/tests/fixtures/duplicate_blocks/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/duplicate_blocks/source/src/lib.rs rename to anneal/v1/tests/fixtures/duplicate_blocks/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_cfg/args.txt b/anneal/v1/tests/fixtures/edge_cases_cfg/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/args.txt rename to anneal/v1/tests/fixtures/edge_cases_cfg/args.txt diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_1_phantom_fn/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_cfg/test_7_3_ghost_spec/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_charon/args.txt b/anneal/v1/tests/fixtures/edge_cases_charon/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_charon/args.txt rename to anneal/v1/tests/fixtures/edge_cases_charon/args.txt diff --git a/anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_charon/test_8_2_unions/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_charon/test_8_2_unions/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_control/args.txt b/anneal/v1/tests/fixtures/edge_cases_control/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_control/args.txt rename to anneal/v1/tests/fixtures/edge_cases_control/args.txt diff --git a/anneal/tests/fixtures/edge_cases_invariants/args.txt b/anneal/v1/tests/fixtures/edge_cases_invariants/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_invariants/args.txt rename to anneal/v1/tests/fixtures/edge_cases_invariants/args.txt diff --git a/anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_invariants/test_4_6_assoc_types/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_logic/args.txt b/anneal/v1/tests/fixtures/edge_cases_logic/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_logic/args.txt rename to anneal/v1/tests/fixtures/edge_cases_logic/args.txt diff --git a/anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_logic/test_5_4_std_types/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_macros/args.txt b/anneal/v1/tests/fixtures/edge_cases_macros/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_macros/args.txt rename to anneal/v1/tests/fixtures/edge_cases_macros/args.txt diff --git a/anneal/tests/fixtures/edge_cases_modules/args.txt b/anneal/v1/tests/fixtures/edge_cases_modules/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/args.txt rename to anneal/v1/tests/fixtures/edge_cases_modules/args.txt diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_1_external_crate/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_modules/test_6_3_renaming/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_mut_refs/args.txt b/anneal/v1/tests/fixtures/edge_cases_mut_refs/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_mut_refs/args.txt rename to anneal/v1/tests/fixtures/edge_cases_mut_refs/args.txt diff --git a/anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_mut_refs/test_3_3_ret_mut/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_naming/args.txt b/anneal/v1/tests/fixtures/edge_cases_naming/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/args.txt rename to anneal/v1/tests/fixtures/edge_cases_naming/args.txt diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_1_lean_keywords_fns/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_2_lean_keywords_args/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_naming/test_1_3_rust_keywords_idents/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_stress/args.txt b/anneal/v1/tests/fixtures/edge_cases_stress/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_stress/args.txt rename to anneal/v1/tests/fixtures/edge_cases_stress/args.txt diff --git a/anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_stress/test_11_2_monolith/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_types/args.txt b/anneal/v1/tests/fixtures/edge_cases_types/args.txt similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/args.txt rename to anneal/v1/tests/fixtures/edge_cases_types/args.txt diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_3_zst/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_3_zst/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_3_zst/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_3_zst/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_3_zst/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_3_zst/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_3_zst/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_3_zst/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_3_zst/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/expected.stderr b/anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/expected.stderr similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/expected.stderr rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/expected.stderr diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_6_nested_refs/source/src/lib.rs diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/anneal.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/anneal.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/anneal.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/anneal.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/source/Cargo.toml b/anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/source/Cargo.toml rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/source/Cargo.toml diff --git a/anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/source/src/lib.rs b/anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/edge_cases_types/test_2_7_arrays/source/src/lib.rs rename to anneal/v1/tests/fixtures/edge_cases_types/test_2_7_arrays/source/src/lib.rs diff --git a/anneal/tests/fixtures/enums_pattern_matching/anneal.toml b/anneal/v1/tests/fixtures/enums_pattern_matching/anneal.toml similarity index 100% rename from anneal/tests/fixtures/enums_pattern_matching/anneal.toml rename to anneal/v1/tests/fixtures/enums_pattern_matching/anneal.toml diff --git a/anneal/tests/fixtures/enums_pattern_matching/expected.stderr b/anneal/v1/tests/fixtures/enums_pattern_matching/expected.stderr similarity index 100% rename from anneal/tests/fixtures/enums_pattern_matching/expected.stderr rename to anneal/v1/tests/fixtures/enums_pattern_matching/expected.stderr diff --git a/anneal/tests/fixtures/enums_pattern_matching/source/Cargo.toml b/anneal/v1/tests/fixtures/enums_pattern_matching/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/enums_pattern_matching/source/Cargo.toml rename to anneal/v1/tests/fixtures/enums_pattern_matching/source/Cargo.toml diff --git a/anneal/tests/fixtures/enums_pattern_matching/source/src/lib.rs b/anneal/v1/tests/fixtures/enums_pattern_matching/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/enums_pattern_matching/source/src/lib.rs rename to anneal/v1/tests/fixtures/enums_pattern_matching/source/src/lib.rs diff --git a/anneal/tests/fixtures/env_interleaved_stdout/anneal.toml b/anneal/v1/tests/fixtures/env_interleaved_stdout/anneal.toml similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/anneal.toml rename to anneal/v1/tests/fixtures/env_interleaved_stdout/anneal.toml diff --git a/anneal/tests/fixtures/env_interleaved_stdout/expected.stderr b/anneal/v1/tests/fixtures/env_interleaved_stdout/expected.stderr similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/expected.stderr rename to anneal/v1/tests/fixtures/env_interleaved_stdout/expected.stderr diff --git a/anneal/tests/fixtures/env_interleaved_stdout/mock_charon.sh b/anneal/v1/tests/fixtures/env_interleaved_stdout/mock_charon.sh similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/mock_charon.sh rename to anneal/v1/tests/fixtures/env_interleaved_stdout/mock_charon.sh diff --git a/anneal/tests/fixtures/env_interleaved_stdout/mock_charon_output.json b/anneal/v1/tests/fixtures/env_interleaved_stdout/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/mock_charon_output.json rename to anneal/v1/tests/fixtures/env_interleaved_stdout/mock_charon_output.json diff --git a/anneal/tests/fixtures/env_interleaved_stdout/source/Cargo.toml b/anneal/v1/tests/fixtures/env_interleaved_stdout/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/source/Cargo.toml rename to anneal/v1/tests/fixtures/env_interleaved_stdout/source/Cargo.toml diff --git a/anneal/tests/fixtures/env_interleaved_stdout/source/src/lib.rs b/anneal/v1/tests/fixtures/env_interleaved_stdout/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/env_interleaved_stdout/source/src/lib.rs rename to anneal/v1/tests/fixtures/env_interleaved_stdout/source/src/lib.rs diff --git a/anneal/tests/fixtures/expand_output/anneal.toml b/anneal/v1/tests/fixtures/expand_output/anneal.toml similarity index 100% rename from anneal/tests/fixtures/expand_output/anneal.toml rename to anneal/v1/tests/fixtures/expand_output/anneal.toml diff --git a/anneal/tests/fixtures/expand_output/expected-aeneas.stdout b/anneal/v1/tests/fixtures/expand_output/expected-aeneas.stdout similarity index 100% rename from anneal/tests/fixtures/expand_output/expected-aeneas.stdout rename to anneal/v1/tests/fixtures/expand_output/expected-aeneas.stdout diff --git a/anneal/tests/fixtures/expand_output/expected-all.stdout b/anneal/v1/tests/fixtures/expand_output/expected-all.stdout similarity index 100% rename from anneal/tests/fixtures/expand_output/expected-all.stdout rename to anneal/v1/tests/fixtures/expand_output/expected-all.stdout diff --git a/anneal/tests/fixtures/expand_output/expected-anneal.stdout b/anneal/v1/tests/fixtures/expand_output/expected-anneal.stdout similarity index 100% rename from anneal/tests/fixtures/expand_output/expected-anneal.stdout rename to anneal/v1/tests/fixtures/expand_output/expected-anneal.stdout diff --git a/anneal/tests/fixtures/expand_output/source/Cargo.toml b/anneal/v1/tests/fixtures/expand_output/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/expand_output/source/Cargo.toml rename to anneal/v1/tests/fixtures/expand_output/source/Cargo.toml diff --git a/anneal/tests/fixtures/expand_output/source/src/lib.rs b/anneal/v1/tests/fixtures/expand_output/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/expand_output/source/src/lib.rs rename to anneal/v1/tests/fixtures/expand_output/source/src/lib.rs diff --git a/anneal/tests/fixtures/extern_never_verified/anneal.toml b/anneal/v1/tests/fixtures/extern_never_verified/anneal.toml similarity index 100% rename from anneal/tests/fixtures/extern_never_verified/anneal.toml rename to anneal/v1/tests/fixtures/extern_never_verified/anneal.toml diff --git a/anneal/tests/fixtures/extern_never_verified/out.txt b/anneal/v1/tests/fixtures/extern_never_verified/out.txt similarity index 100% rename from anneal/tests/fixtures/extern_never_verified/out.txt rename to anneal/v1/tests/fixtures/extern_never_verified/out.txt diff --git a/anneal/tests/fixtures/extern_never_verified/source/Cargo.toml b/anneal/v1/tests/fixtures/extern_never_verified/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/extern_never_verified/source/Cargo.toml rename to anneal/v1/tests/fixtures/extern_never_verified/source/Cargo.toml diff --git a/anneal/tests/fixtures/extern_never_verified/source/src/lib.rs b/anneal/v1/tests/fixtures/extern_never_verified/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/extern_never_verified/source/src/lib.rs rename to anneal/v1/tests/fixtures/extern_never_verified/source/src/lib.rs diff --git a/anneal/tests/fixtures/external_dep_failure/anneal.toml b/anneal/v1/tests/fixtures/external_dep_failure/anneal.toml similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/anneal.toml rename to anneal/v1/tests/fixtures/external_dep_failure/anneal.toml diff --git a/anneal/tests/fixtures/external_dep_failure/source/Cargo.toml b/anneal/v1/tests/fixtures/external_dep_failure/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/source/Cargo.toml rename to anneal/v1/tests/fixtures/external_dep_failure/source/Cargo.toml diff --git a/anneal/tests/fixtures/external_dep_failure/source/app/Cargo.toml b/anneal/v1/tests/fixtures/external_dep_failure/source/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/source/app/Cargo.toml rename to anneal/v1/tests/fixtures/external_dep_failure/source/app/Cargo.toml diff --git a/anneal/tests/fixtures/external_dep_failure/source/app/src/lib.rs b/anneal/v1/tests/fixtures/external_dep_failure/source/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/source/app/src/lib.rs rename to anneal/v1/tests/fixtures/external_dep_failure/source/app/src/lib.rs diff --git a/anneal/tests/fixtures/external_dep_failure/source/utils/Cargo.toml b/anneal/v1/tests/fixtures/external_dep_failure/source/utils/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/source/utils/Cargo.toml rename to anneal/v1/tests/fixtures/external_dep_failure/source/utils/Cargo.toml diff --git a/anneal/tests/fixtures/external_dep_failure/source/utils/src/lib.rs b/anneal/v1/tests/fixtures/external_dep_failure/source/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/external_dep_failure/source/utils/src/lib.rs rename to anneal/v1/tests/fixtures/external_dep_failure/source/utils/src/lib.rs diff --git a/anneal/tests/fixtures/external_path_dependency/anneal.toml b/anneal/v1/tests/fixtures/external_path_dependency/anneal.toml similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/anneal.toml rename to anneal/v1/tests/fixtures/external_path_dependency/anneal.toml diff --git a/anneal/tests/fixtures/external_path_dependency/source/external_dep/Cargo.toml b/anneal/v1/tests/fixtures/external_path_dependency/source/external_dep/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/source/external_dep/Cargo.toml rename to anneal/v1/tests/fixtures/external_path_dependency/source/external_dep/Cargo.toml diff --git a/anneal/tests/fixtures/external_path_dependency/source/external_dep/src/lib.rs b/anneal/v1/tests/fixtures/external_path_dependency/source/external_dep/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/source/external_dep/src/lib.rs rename to anneal/v1/tests/fixtures/external_path_dependency/source/external_dep/src/lib.rs diff --git a/anneal/tests/fixtures/external_path_dependency/source/workspace/Cargo.toml b/anneal/v1/tests/fixtures/external_path_dependency/source/workspace/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/source/workspace/Cargo.toml rename to anneal/v1/tests/fixtures/external_path_dependency/source/workspace/Cargo.toml diff --git a/anneal/tests/fixtures/external_path_dependency/source/workspace/app/Cargo.toml b/anneal/v1/tests/fixtures/external_path_dependency/source/workspace/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/source/workspace/app/Cargo.toml rename to anneal/v1/tests/fixtures/external_path_dependency/source/workspace/app/Cargo.toml diff --git a/anneal/tests/fixtures/external_path_dependency/source/workspace/app/src/lib.rs b/anneal/v1/tests/fixtures/external_path_dependency/source/workspace/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/external_path_dependency/source/workspace/app/src/lib.rs rename to anneal/v1/tests/fixtures/external_path_dependency/source/workspace/app/src/lib.rs diff --git a/anneal/tests/fixtures/fs_missing_source/anneal.toml b/anneal/v1/tests/fixtures/fs_missing_source/anneal.toml similarity index 100% rename from anneal/tests/fixtures/fs_missing_source/anneal.toml rename to anneal/v1/tests/fixtures/fs_missing_source/anneal.toml diff --git a/anneal/tests/fixtures/fs_missing_source/expected.stderr b/anneal/v1/tests/fixtures/fs_missing_source/expected.stderr similarity index 100% rename from anneal/tests/fixtures/fs_missing_source/expected.stderr rename to anneal/v1/tests/fixtures/fs_missing_source/expected.stderr diff --git a/anneal/tests/fixtures/fs_missing_source/mock_charon_output.json b/anneal/v1/tests/fixtures/fs_missing_source/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/fs_missing_source/mock_charon_output.json rename to anneal/v1/tests/fixtures/fs_missing_source/mock_charon_output.json diff --git a/anneal/tests/fixtures/fs_missing_source/source/Cargo.toml b/anneal/v1/tests/fixtures/fs_missing_source/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/fs_missing_source/source/Cargo.toml rename to anneal/v1/tests/fixtures/fs_missing_source/source/Cargo.toml diff --git a/anneal/tests/fixtures/fs_missing_source/source/src/lib.rs b/anneal/v1/tests/fixtures/fs_missing_source/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/fs_missing_source/source/src/lib.rs rename to anneal/v1/tests/fixtures/fs_missing_source/source/src/lib.rs diff --git a/anneal/tests/fixtures/generate_output/anneal.toml b/anneal/v1/tests/fixtures/generate_output/anneal.toml similarity index 100% rename from anneal/tests/fixtures/generate_output/anneal.toml rename to anneal/v1/tests/fixtures/generate_output/anneal.toml diff --git a/anneal/tests/fixtures/generate_output/expected-generate.stdout b/anneal/v1/tests/fixtures/generate_output/expected-generate.stdout similarity index 100% rename from anneal/tests/fixtures/generate_output/expected-generate.stdout rename to anneal/v1/tests/fixtures/generate_output/expected-generate.stdout diff --git a/anneal/tests/fixtures/generate_output/source/Cargo.toml b/anneal/v1/tests/fixtures/generate_output/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/generate_output/source/Cargo.toml rename to anneal/v1/tests/fixtures/generate_output/source/Cargo.toml diff --git a/anneal/tests/fixtures/generate_output/source/src/lib.rs b/anneal/v1/tests/fixtures/generate_output/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/generate_output/source/src/lib.rs rename to anneal/v1/tests/fixtures/generate_output/source/src/lib.rs diff --git a/anneal/tests/fixtures/hidden_syntax_error/anneal.toml b/anneal/v1/tests/fixtures/hidden_syntax_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/hidden_syntax_error/anneal.toml rename to anneal/v1/tests/fixtures/hidden_syntax_error/anneal.toml diff --git a/anneal/tests/fixtures/hidden_syntax_error/expected.stderr b/anneal/v1/tests/fixtures/hidden_syntax_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/hidden_syntax_error/expected.stderr rename to anneal/v1/tests/fixtures/hidden_syntax_error/expected.stderr diff --git a/anneal/tests/fixtures/hidden_syntax_error/source/Cargo.toml b/anneal/v1/tests/fixtures/hidden_syntax_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/hidden_syntax_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/hidden_syntax_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/hidden_syntax_error/source/src/lib.rs b/anneal/v1/tests/fixtures/hidden_syntax_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/hidden_syntax_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/hidden_syntax_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/idempotency/anneal.toml b/anneal/v1/tests/fixtures/idempotency/anneal.toml similarity index 100% rename from anneal/tests/fixtures/idempotency/anneal.toml rename to anneal/v1/tests/fixtures/idempotency/anneal.toml diff --git a/anneal/tests/fixtures/idempotency/source/Cargo.toml b/anneal/v1/tests/fixtures/idempotency/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/idempotency/source/Cargo.toml rename to anneal/v1/tests/fixtures/idempotency/source/Cargo.toml diff --git a/anneal/tests/fixtures/idempotency/source/src/lib.rs b/anneal/v1/tests/fixtures/idempotency/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/idempotency/source/src/lib.rs rename to anneal/v1/tests/fixtures/idempotency/source/src/lib.rs diff --git a/anneal/tests/fixtures/is_valid_verification/anneal.toml b/anneal/v1/tests/fixtures/is_valid_verification/anneal.toml similarity index 100% rename from anneal/tests/fixtures/is_valid_verification/anneal.toml rename to anneal/v1/tests/fixtures/is_valid_verification/anneal.toml diff --git a/anneal/tests/fixtures/is_valid_verification/expected.stderr b/anneal/v1/tests/fixtures/is_valid_verification/expected.stderr similarity index 100% rename from anneal/tests/fixtures/is_valid_verification/expected.stderr rename to anneal/v1/tests/fixtures/is_valid_verification/expected.stderr diff --git a/anneal/tests/fixtures/is_valid_verification/source/Cargo.toml b/anneal/v1/tests/fixtures/is_valid_verification/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/is_valid_verification/source/Cargo.toml rename to anneal/v1/tests/fixtures/is_valid_verification/source/Cargo.toml diff --git a/anneal/tests/fixtures/is_valid_verification/source/src/lib.rs b/anneal/v1/tests/fixtures/is_valid_verification/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/is_valid_verification/source/src/lib.rs rename to anneal/v1/tests/fixtures/is_valid_verification/source/src/lib.rs diff --git a/anneal/tests/fixtures/json_code_suggestions/anneal.toml b/anneal/v1/tests/fixtures/json_code_suggestions/anneal.toml similarity index 100% rename from anneal/tests/fixtures/json_code_suggestions/anneal.toml rename to anneal/v1/tests/fixtures/json_code_suggestions/anneal.toml diff --git a/anneal/tests/fixtures/json_code_suggestions/expected.stderr b/anneal/v1/tests/fixtures/json_code_suggestions/expected.stderr similarity index 100% rename from anneal/tests/fixtures/json_code_suggestions/expected.stderr rename to anneal/v1/tests/fixtures/json_code_suggestions/expected.stderr diff --git a/anneal/tests/fixtures/json_code_suggestions/mock_charon_output.json b/anneal/v1/tests/fixtures/json_code_suggestions/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/json_code_suggestions/mock_charon_output.json rename to anneal/v1/tests/fixtures/json_code_suggestions/mock_charon_output.json diff --git a/anneal/tests/fixtures/json_code_suggestions/source/Cargo.toml b/anneal/v1/tests/fixtures/json_code_suggestions/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/json_code_suggestions/source/Cargo.toml rename to anneal/v1/tests/fixtures/json_code_suggestions/source/Cargo.toml diff --git a/anneal/tests/fixtures/json_code_suggestions/source/src/lib.rs b/anneal/v1/tests/fixtures/json_code_suggestions/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/json_code_suggestions/source/src/lib.rs rename to anneal/v1/tests/fixtures/json_code_suggestions/source/src/lib.rs diff --git a/anneal/tests/fixtures/json_linker_error/anneal.toml b/anneal/v1/tests/fixtures/json_linker_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/json_linker_error/anneal.toml rename to anneal/v1/tests/fixtures/json_linker_error/anneal.toml diff --git a/anneal/tests/fixtures/json_linker_error/expected.stderr b/anneal/v1/tests/fixtures/json_linker_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/json_linker_error/expected.stderr rename to anneal/v1/tests/fixtures/json_linker_error/expected.stderr diff --git a/anneal/tests/fixtures/json_linker_error/mock_charon_output.json b/anneal/v1/tests/fixtures/json_linker_error/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/json_linker_error/mock_charon_output.json rename to anneal/v1/tests/fixtures/json_linker_error/mock_charon_output.json diff --git a/anneal/tests/fixtures/json_linker_error/source/Cargo.toml b/anneal/v1/tests/fixtures/json_linker_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/json_linker_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/json_linker_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/json_linker_error/source/src/lib.rs b/anneal/v1/tests/fixtures/json_linker_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/json_linker_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/json_linker_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/json_nested_children/anneal.toml b/anneal/v1/tests/fixtures/json_nested_children/anneal.toml similarity index 100% rename from anneal/tests/fixtures/json_nested_children/anneal.toml rename to anneal/v1/tests/fixtures/json_nested_children/anneal.toml diff --git a/anneal/tests/fixtures/json_nested_children/expected.stderr b/anneal/v1/tests/fixtures/json_nested_children/expected.stderr similarity index 100% rename from anneal/tests/fixtures/json_nested_children/expected.stderr rename to anneal/v1/tests/fixtures/json_nested_children/expected.stderr diff --git a/anneal/tests/fixtures/json_nested_children/mock_charon_output.json b/anneal/v1/tests/fixtures/json_nested_children/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/json_nested_children/mock_charon_output.json rename to anneal/v1/tests/fixtures/json_nested_children/mock_charon_output.json diff --git a/anneal/tests/fixtures/json_nested_children/source/Cargo.toml b/anneal/v1/tests/fixtures/json_nested_children/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/json_nested_children/source/Cargo.toml rename to anneal/v1/tests/fixtures/json_nested_children/source/Cargo.toml diff --git a/anneal/tests/fixtures/json_nested_children/source/src/lib.rs b/anneal/v1/tests/fixtures/json_nested_children/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/json_nested_children/source/src/lib.rs rename to anneal/v1/tests/fixtures/json_nested_children/source/src/lib.rs diff --git a/anneal/tests/fixtures/lean_edge_cases/anneal.toml b/anneal/v1/tests/fixtures/lean_edge_cases/anneal.toml similarity index 100% rename from anneal/tests/fixtures/lean_edge_cases/anneal.toml rename to anneal/v1/tests/fixtures/lean_edge_cases/anneal.toml diff --git a/anneal/tests/fixtures/lean_edge_cases/source/Cargo.toml b/anneal/v1/tests/fixtures/lean_edge_cases/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/lean_edge_cases/source/Cargo.toml rename to anneal/v1/tests/fixtures/lean_edge_cases/source/Cargo.toml diff --git a/anneal/tests/fixtures/lean_edge_cases/source/src/lib.rs b/anneal/v1/tests/fixtures/lean_edge_cases/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/lean_edge_cases/source/src/lib.rs rename to anneal/v1/tests/fixtures/lean_edge_cases/source/src/lib.rs diff --git a/anneal/tests/fixtures/lean_generation/anneal.toml b/anneal/v1/tests/fixtures/lean_generation/anneal.toml similarity index 100% rename from anneal/tests/fixtures/lean_generation/anneal.toml rename to anneal/v1/tests/fixtures/lean_generation/anneal.toml diff --git a/anneal/tests/fixtures/lean_generation/expected.stderr b/anneal/v1/tests/fixtures/lean_generation/expected.stderr similarity index 100% rename from anneal/tests/fixtures/lean_generation/expected.stderr rename to anneal/v1/tests/fixtures/lean_generation/expected.stderr diff --git a/anneal/tests/fixtures/lean_generation/source/Cargo.lock b/anneal/v1/tests/fixtures/lean_generation/source/Cargo.lock similarity index 100% rename from anneal/tests/fixtures/lean_generation/source/Cargo.lock rename to anneal/v1/tests/fixtures/lean_generation/source/Cargo.lock diff --git a/anneal/tests/fixtures/lean_generation/source/Cargo.toml b/anneal/v1/tests/fixtures/lean_generation/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/lean_generation/source/Cargo.toml rename to anneal/v1/tests/fixtures/lean_generation/source/Cargo.toml diff --git a/anneal/tests/fixtures/lean_generation/source/src/lib.rs b/anneal/v1/tests/fixtures/lean_generation/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/lean_generation/source/src/lib.rs rename to anneal/v1/tests/fixtures/lean_generation/source/src/lib.rs diff --git a/anneal/tests/fixtures/libtest_ptr.rlib b/anneal/v1/tests/fixtures/libtest_ptr.rlib similarity index 100% rename from anneal/tests/fixtures/libtest_ptr.rlib rename to anneal/v1/tests/fixtures/libtest_ptr.rlib diff --git a/anneal/tests/fixtures/map_canonical_mismatch/anneal.toml b/anneal/v1/tests/fixtures/map_canonical_mismatch/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/anneal.toml rename to anneal/v1/tests/fixtures/map_canonical_mismatch/anneal.toml diff --git a/anneal/tests/fixtures/map_canonical_mismatch/expected.stderr b/anneal/v1/tests/fixtures/map_canonical_mismatch/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/expected.stderr rename to anneal/v1/tests/fixtures/map_canonical_mismatch/expected.stderr diff --git a/anneal/tests/fixtures/map_canonical_mismatch/mock_charon_output.json b/anneal/v1/tests/fixtures/map_canonical_mismatch/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_canonical_mismatch/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/Cargo.toml b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/src/lib.rs b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/src/macros.rs b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_canonical_mismatch/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_canonical_mismatch/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_canonical_mismatch/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/map_external_dep/anneal.toml b/anneal/v1/tests/fixtures/map_external_dep/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_external_dep/anneal.toml rename to anneal/v1/tests/fixtures/map_external_dep/anneal.toml diff --git a/anneal/tests/fixtures/map_external_dep/expected.stderr b/anneal/v1/tests/fixtures/map_external_dep/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_external_dep/expected.stderr rename to anneal/v1/tests/fixtures/map_external_dep/expected.stderr diff --git a/anneal/tests/fixtures/map_external_dep/mock_charon_output.json b/anneal/v1/tests/fixtures/map_external_dep/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_external_dep/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_external_dep/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_external_dep/source/Cargo.toml b/anneal/v1/tests/fixtures/map_external_dep/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_external_dep/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_external_dep/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_external_dep/source/src/lib.rs b/anneal/v1/tests/fixtures/map_external_dep/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_external_dep/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_external_dep/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_macro_expansion/anneal.toml b/anneal/v1/tests/fixtures/map_macro_expansion/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/anneal.toml rename to anneal/v1/tests/fixtures/map_macro_expansion/anneal.toml diff --git a/anneal/tests/fixtures/map_macro_expansion/expected.stderr b/anneal/v1/tests/fixtures/map_macro_expansion/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/expected.stderr rename to anneal/v1/tests/fixtures/map_macro_expansion/expected.stderr diff --git a/anneal/tests/fixtures/map_macro_expansion/mock_charon_output.json b/anneal/v1/tests/fixtures/map_macro_expansion/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_macro_expansion/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_macro_expansion/source/Cargo.toml b/anneal/v1/tests/fixtures/map_macro_expansion/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_macro_expansion/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_macro_expansion/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_macro_expansion/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_macro_expansion/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_macro_expansion/source/src/lib.rs b/anneal/v1/tests/fixtures/map_macro_expansion/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_macro_expansion/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_macro_expansion/source/src/macros.rs b/anneal/v1/tests/fixtures/map_macro_expansion/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_macro_expansion/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_macro_expansion/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_macro_expansion/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_macro_expansion/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_macro_expansion/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_macro_expansion/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_macro_expansion/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_macro_expansion/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/anneal.toml b/anneal/v1/tests/fixtures/map_mixed_diagnostics/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/anneal.toml rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/anneal.toml diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/expected.stderr b/anneal/v1/tests/fixtures/map_mixed_diagnostics/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/expected.stderr rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/expected.stderr diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/mock_charon_output.json b/anneal/v1/tests/fixtures/map_mixed_diagnostics/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/Cargo.toml b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/src/lib.rs b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/src/macros.rs b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_mixed_diagnostics/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_mixed_diagnostics/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_mixed_diagnostics/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/map_path_traversal/anneal.toml b/anneal/v1/tests/fixtures/map_path_traversal/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_path_traversal/anneal.toml rename to anneal/v1/tests/fixtures/map_path_traversal/anneal.toml diff --git a/anneal/tests/fixtures/map_path_traversal/expected.stderr b/anneal/v1/tests/fixtures/map_path_traversal/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_path_traversal/expected.stderr rename to anneal/v1/tests/fixtures/map_path_traversal/expected.stderr diff --git a/anneal/tests/fixtures/map_path_traversal/mock_charon_output.json b/anneal/v1/tests/fixtures/map_path_traversal/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_path_traversal/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_path_traversal/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_path_traversal/source/Cargo.toml b/anneal/v1/tests/fixtures/map_path_traversal/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_path_traversal/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_path_traversal/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_path_traversal/source/src/lib.rs b/anneal/v1/tests/fixtures/map_path_traversal/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_path_traversal/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_path_traversal/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_relative_path/anneal.toml b/anneal/v1/tests/fixtures/map_relative_path/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_relative_path/anneal.toml rename to anneal/v1/tests/fixtures/map_relative_path/anneal.toml diff --git a/anneal/tests/fixtures/map_relative_path/expected.stderr b/anneal/v1/tests/fixtures/map_relative_path/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_relative_path/expected.stderr rename to anneal/v1/tests/fixtures/map_relative_path/expected.stderr diff --git a/anneal/tests/fixtures/map_relative_path/mock_charon_output.json b/anneal/v1/tests/fixtures/map_relative_path/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_relative_path/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_relative_path/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_relative_path/source/Cargo.toml b/anneal/v1/tests/fixtures/map_relative_path/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_relative_path/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_relative_path/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_relative_path/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_relative_path/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_relative_path/source/src/lib.rs b/anneal/v1/tests/fixtures/map_relative_path/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_relative_path/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_relative_path/source/src/macros.rs b/anneal/v1/tests/fixtures/map_relative_path/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_relative_path/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_relative_path/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_relative_path/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_relative_path/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_relative_path/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_relative_path/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_relative_path/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_relative_path/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/map_std_lib/anneal.toml b/anneal/v1/tests/fixtures/map_std_lib/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_std_lib/anneal.toml rename to anneal/v1/tests/fixtures/map_std_lib/anneal.toml diff --git a/anneal/tests/fixtures/map_std_lib/expected.stderr b/anneal/v1/tests/fixtures/map_std_lib/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_std_lib/expected.stderr rename to anneal/v1/tests/fixtures/map_std_lib/expected.stderr diff --git a/anneal/tests/fixtures/map_std_lib/mock_charon_output.json b/anneal/v1/tests/fixtures/map_std_lib/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_std_lib/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_std_lib/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_std_lib/source/Cargo.toml b/anneal/v1/tests/fixtures/map_std_lib/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_std_lib/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_std_lib/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_std_lib/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_std_lib/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_std_lib/source/src/lib.rs b/anneal/v1/tests/fixtures/map_std_lib/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_std_lib/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_std_lib/source/src/macros.rs b/anneal/v1/tests/fixtures/map_std_lib/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_std_lib/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_std_lib/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_std_lib/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_std_lib/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_std_lib/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_std_lib/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_std_lib/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_std_lib/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/map_std_library/anneal.toml b/anneal/v1/tests/fixtures/map_std_library/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_std_library/anneal.toml rename to anneal/v1/tests/fixtures/map_std_library/anneal.toml diff --git a/anneal/tests/fixtures/map_std_library/expected.stderr b/anneal/v1/tests/fixtures/map_std_library/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_std_library/expected.stderr rename to anneal/v1/tests/fixtures/map_std_library/expected.stderr diff --git a/anneal/tests/fixtures/map_std_library/mock_charon_output.json b/anneal/v1/tests/fixtures/map_std_library/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_std_library/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_std_library/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_std_library/source/Cargo.toml b/anneal/v1/tests/fixtures/map_std_library/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_std_library/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_std_library/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_std_library/source/src/lib.rs b/anneal/v1/tests/fixtures/map_std_library/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_std_library/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_std_library/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_symlinked_file/anneal.toml b/anneal/v1/tests/fixtures/map_symlinked_file/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/anneal.toml rename to anneal/v1/tests/fixtures/map_symlinked_file/anneal.toml diff --git a/anneal/tests/fixtures/map_symlinked_file/expected.stderr b/anneal/v1/tests/fixtures/map_symlinked_file/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/expected.stderr rename to anneal/v1/tests/fixtures/map_symlinked_file/expected.stderr diff --git a/anneal/tests/fixtures/map_symlinked_file/mock_charon_output.json b/anneal/v1/tests/fixtures/map_symlinked_file/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_symlinked_file/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_symlinked_file/source/Cargo.toml b/anneal/v1/tests/fixtures/map_symlinked_file/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_symlinked_file/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_symlinked_file/source/src/lib.rs b/anneal/v1/tests/fixtures/map_symlinked_file/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_symlinked_file/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_symlinked_file/source/src/untransformed.rs b/anneal/v1/tests/fixtures/map_symlinked_file/source/src/untransformed.rs similarity index 100% rename from anneal/tests/fixtures/map_symlinked_file/source/src/untransformed.rs rename to anneal/v1/tests/fixtures/map_symlinked_file/source/src/untransformed.rs diff --git a/anneal/tests/fixtures/map_workspace_path_dep/anneal.toml b/anneal/v1/tests/fixtures/map_workspace_path_dep/anneal.toml similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/anneal.toml rename to anneal/v1/tests/fixtures/map_workspace_path_dep/anneal.toml diff --git a/anneal/tests/fixtures/map_workspace_path_dep/expected.stderr b/anneal/v1/tests/fixtures/map_workspace_path_dep/expected.stderr similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/expected.stderr rename to anneal/v1/tests/fixtures/map_workspace_path_dep/expected.stderr diff --git a/anneal/tests/fixtures/map_workspace_path_dep/mock_charon_output.json b/anneal/v1/tests/fixtures/map_workspace_path_dep/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/mock_charon_output.json rename to anneal/v1/tests/fixtures/map_workspace_path_dep/mock_charon_output.json diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/Cargo.toml b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/Cargo.toml rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/Cargo.toml diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/src/lib.rs b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/src/lib.rs rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/lib.rs diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/src/macros.rs b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/src/macros.rs rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/macros.rs diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/src/rewritten.rs b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/map_workspace_path_dep/source/src/symlinked.rs b/anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/map_workspace_path_dep/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/map_workspace_path_dep/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/missing_output/anneal.toml b/anneal/v1/tests/fixtures/missing_output/anneal.toml similarity index 100% rename from anneal/tests/fixtures/missing_output/anneal.toml rename to anneal/v1/tests/fixtures/missing_output/anneal.toml diff --git a/anneal/tests/fixtures/missing_output/expected.stderr b/anneal/v1/tests/fixtures/missing_output/expected.stderr similarity index 100% rename from anneal/tests/fixtures/missing_output/expected.stderr rename to anneal/v1/tests/fixtures/missing_output/expected.stderr diff --git a/anneal/tests/fixtures/missing_output/mock_aeneas.sh b/anneal/v1/tests/fixtures/missing_output/mock_aeneas.sh similarity index 100% rename from anneal/tests/fixtures/missing_output/mock_aeneas.sh rename to anneal/v1/tests/fixtures/missing_output/mock_aeneas.sh diff --git a/anneal/tests/fixtures/missing_output/source/Cargo.toml b/anneal/v1/tests/fixtures/missing_output/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/missing_output/source/Cargo.toml rename to anneal/v1/tests/fixtures/missing_output/source/Cargo.toml diff --git a/anneal/tests/fixtures/missing_output/source/src/lib.rs b/anneal/v1/tests/fixtures/missing_output/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/missing_output/source/src/lib.rs rename to anneal/v1/tests/fixtures/missing_output/source/src/lib.rs diff --git a/anneal/tests/fixtures/mixed_workspace/anneal.toml b/anneal/v1/tests/fixtures/mixed_workspace/anneal.toml similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/anneal.toml rename to anneal/v1/tests/fixtures/mixed_workspace/anneal.toml diff --git a/anneal/tests/fixtures/mixed_workspace/source/Cargo.toml b/anneal/v1/tests/fixtures/mixed_workspace/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/source/Cargo.toml rename to anneal/v1/tests/fixtures/mixed_workspace/source/Cargo.toml diff --git a/anneal/tests/fixtures/mixed_workspace/source/crates/app/Cargo.toml b/anneal/v1/tests/fixtures/mixed_workspace/source/crates/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/source/crates/app/Cargo.toml rename to anneal/v1/tests/fixtures/mixed_workspace/source/crates/app/Cargo.toml diff --git a/anneal/tests/fixtures/mixed_workspace/source/crates/app/src/lib.rs b/anneal/v1/tests/fixtures/mixed_workspace/source/crates/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/source/crates/app/src/lib.rs rename to anneal/v1/tests/fixtures/mixed_workspace/source/crates/app/src/lib.rs diff --git a/anneal/tests/fixtures/mixed_workspace/source/crates/dep/Cargo.toml b/anneal/v1/tests/fixtures/mixed_workspace/source/crates/dep/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/source/crates/dep/Cargo.toml rename to anneal/v1/tests/fixtures/mixed_workspace/source/crates/dep/Cargo.toml diff --git a/anneal/tests/fixtures/mixed_workspace/source/crates/dep/src/lib.rs b/anneal/v1/tests/fixtures/mixed_workspace/source/crates/dep/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/mixed_workspace/source/crates/dep/src/lib.rs rename to anneal/v1/tests/fixtures/mixed_workspace/source/crates/dep/src/lib.rs diff --git a/anneal/tests/fixtures/module_resolution/anneal.toml b/anneal/v1/tests/fixtures/module_resolution/anneal.toml similarity index 100% rename from anneal/tests/fixtures/module_resolution/anneal.toml rename to anneal/v1/tests/fixtures/module_resolution/anneal.toml diff --git a/anneal/tests/fixtures/module_resolution/extra.rs b/anneal/v1/tests/fixtures/module_resolution/extra.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/extra.rs rename to anneal/v1/tests/fixtures/module_resolution/extra.rs diff --git a/anneal/tests/fixtures/module_resolution/source/Cargo.toml b/anneal/v1/tests/fixtures/module_resolution/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/Cargo.toml rename to anneal/v1/tests/fixtures/module_resolution/source/Cargo.toml diff --git a/anneal/tests/fixtures/module_resolution/source/src/a.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/a.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/a.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/a.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/a/b.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/a/b.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/a/b.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/a/b.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/bar/mod.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/bar/mod.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/bar/mod.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/bar/mod.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/c.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/c.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/c.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/c.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/foo.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/foo.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/foo.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/foo.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/lib.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/lib.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/lib.rs diff --git a/anneal/tests/fixtures/module_resolution/source/src/sys/unix.rs b/anneal/v1/tests/fixtures/module_resolution/source/src/sys/unix.rs similarity index 100% rename from anneal/tests/fixtures/module_resolution/source/src/sys/unix.rs rename to anneal/v1/tests/fixtures/module_resolution/source/src/sys/unix.rs diff --git a/anneal/tests/fixtures/multi_artifact/anneal.toml b/anneal/v1/tests/fixtures/multi_artifact/anneal.toml similarity index 100% rename from anneal/tests/fixtures/multi_artifact/anneal.toml rename to anneal/v1/tests/fixtures/multi_artifact/anneal.toml diff --git a/anneal/tests/fixtures/multi_artifact/expected b/anneal/v1/tests/fixtures/multi_artifact/expected similarity index 100% rename from anneal/tests/fixtures/multi_artifact/expected rename to anneal/v1/tests/fixtures/multi_artifact/expected diff --git a/anneal/tests/fixtures/multi_artifact/expected.stderr b/anneal/v1/tests/fixtures/multi_artifact/expected.stderr similarity index 100% rename from anneal/tests/fixtures/multi_artifact/expected.stderr rename to anneal/v1/tests/fixtures/multi_artifact/expected.stderr diff --git a/anneal/tests/fixtures/multi_artifact/source/Cargo.toml b/anneal/v1/tests/fixtures/multi_artifact/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/multi_artifact/source/Cargo.toml rename to anneal/v1/tests/fixtures/multi_artifact/source/Cargo.toml diff --git a/anneal/tests/fixtures/multi_artifact/source/src/lib.rs b/anneal/v1/tests/fixtures/multi_artifact/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/multi_artifact/source/src/lib.rs rename to anneal/v1/tests/fixtures/multi_artifact/source/src/lib.rs diff --git a/anneal/tests/fixtures/multiple_errors/anneal.toml b/anneal/v1/tests/fixtures/multiple_errors/anneal.toml similarity index 100% rename from anneal/tests/fixtures/multiple_errors/anneal.toml rename to anneal/v1/tests/fixtures/multiple_errors/anneal.toml diff --git a/anneal/tests/fixtures/multiple_errors/expected.stderr b/anneal/v1/tests/fixtures/multiple_errors/expected.stderr similarity index 100% rename from anneal/tests/fixtures/multiple_errors/expected.stderr rename to anneal/v1/tests/fixtures/multiple_errors/expected.stderr diff --git a/anneal/tests/fixtures/multiple_errors/source/Cargo.toml b/anneal/v1/tests/fixtures/multiple_errors/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/multiple_errors/source/Cargo.toml rename to anneal/v1/tests/fixtures/multiple_errors/source/Cargo.toml diff --git a/anneal/tests/fixtures/multiple_errors/source/src/a.rs b/anneal/v1/tests/fixtures/multiple_errors/source/src/a.rs similarity index 100% rename from anneal/tests/fixtures/multiple_errors/source/src/a.rs rename to anneal/v1/tests/fixtures/multiple_errors/source/src/a.rs diff --git a/anneal/tests/fixtures/multiple_errors/source/src/b.rs b/anneal/v1/tests/fixtures/multiple_errors/source/src/b.rs similarity index 100% rename from anneal/tests/fixtures/multiple_errors/source/src/b.rs rename to anneal/v1/tests/fixtures/multiple_errors/source/src/b.rs diff --git a/anneal/tests/fixtures/multiple_errors/source/src/lib.rs b/anneal/v1/tests/fixtures/multiple_errors/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/multiple_errors/source/src/lib.rs rename to anneal/v1/tests/fixtures/multiple_errors/source/src/lib.rs diff --git a/anneal/tests/fixtures/named_bounds_failures/anneal.toml b/anneal/v1/tests/fixtures/named_bounds_failures/anneal.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_failures/anneal.toml rename to anneal/v1/tests/fixtures/named_bounds_failures/anneal.toml diff --git a/anneal/tests/fixtures/named_bounds_failures/expected.stderr b/anneal/v1/tests/fixtures/named_bounds_failures/expected.stderr similarity index 100% rename from anneal/tests/fixtures/named_bounds_failures/expected.stderr rename to anneal/v1/tests/fixtures/named_bounds_failures/expected.stderr diff --git a/anneal/tests/fixtures/named_bounds_failures/source/Cargo.toml b/anneal/v1/tests/fixtures/named_bounds_failures/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_failures/source/Cargo.toml rename to anneal/v1/tests/fixtures/named_bounds_failures/source/Cargo.toml diff --git a/anneal/tests/fixtures/named_bounds_failures/source/src/lib.rs b/anneal/v1/tests/fixtures/named_bounds_failures/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/named_bounds_failures/source/src/lib.rs rename to anneal/v1/tests/fixtures/named_bounds_failures/source/src/lib.rs diff --git a/anneal/tests/fixtures/named_bounds_lean_failures/anneal.toml b/anneal/v1/tests/fixtures/named_bounds_lean_failures/anneal.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_lean_failures/anneal.toml rename to anneal/v1/tests/fixtures/named_bounds_lean_failures/anneal.toml diff --git a/anneal/tests/fixtures/named_bounds_lean_failures/expected.stderr b/anneal/v1/tests/fixtures/named_bounds_lean_failures/expected.stderr similarity index 100% rename from anneal/tests/fixtures/named_bounds_lean_failures/expected.stderr rename to anneal/v1/tests/fixtures/named_bounds_lean_failures/expected.stderr diff --git a/anneal/tests/fixtures/named_bounds_lean_failures/source/Cargo.toml b/anneal/v1/tests/fixtures/named_bounds_lean_failures/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_lean_failures/source/Cargo.toml rename to anneal/v1/tests/fixtures/named_bounds_lean_failures/source/Cargo.toml diff --git a/anneal/tests/fixtures/named_bounds_lean_failures/source/src/lib.rs b/anneal/v1/tests/fixtures/named_bounds_lean_failures/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/named_bounds_lean_failures/source/src/lib.rs rename to anneal/v1/tests/fixtures/named_bounds_lean_failures/source/src/lib.rs diff --git a/anneal/tests/fixtures/named_bounds_validation_failures/anneal.toml b/anneal/v1/tests/fixtures/named_bounds_validation_failures/anneal.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_validation_failures/anneal.toml rename to anneal/v1/tests/fixtures/named_bounds_validation_failures/anneal.toml diff --git a/anneal/tests/fixtures/named_bounds_validation_failures/expected.stderr b/anneal/v1/tests/fixtures/named_bounds_validation_failures/expected.stderr similarity index 100% rename from anneal/tests/fixtures/named_bounds_validation_failures/expected.stderr rename to anneal/v1/tests/fixtures/named_bounds_validation_failures/expected.stderr diff --git a/anneal/tests/fixtures/named_bounds_validation_failures/source/Cargo.toml b/anneal/v1/tests/fixtures/named_bounds_validation_failures/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/named_bounds_validation_failures/source/Cargo.toml rename to anneal/v1/tests/fixtures/named_bounds_validation_failures/source/Cargo.toml diff --git a/anneal/tests/fixtures/named_bounds_validation_failures/source/src/lib.rs b/anneal/v1/tests/fixtures/named_bounds_validation_failures/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/named_bounds_validation_failures/source/src/lib.rs rename to anneal/v1/tests/fixtures/named_bounds_validation_failures/source/src/lib.rs diff --git a/anneal/tests/fixtures/nested_item_error/anneal.toml b/anneal/v1/tests/fixtures/nested_item_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/nested_item_error/anneal.toml rename to anneal/v1/tests/fixtures/nested_item_error/anneal.toml diff --git a/anneal/tests/fixtures/nested_item_error/expected.stderr b/anneal/v1/tests/fixtures/nested_item_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/nested_item_error/expected.stderr rename to anneal/v1/tests/fixtures/nested_item_error/expected.stderr diff --git a/anneal/tests/fixtures/nested_item_error/source/Cargo.toml b/anneal/v1/tests/fixtures/nested_item_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/nested_item_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/nested_item_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/nested_item_error/source/src/lib.rs b/anneal/v1/tests/fixtures/nested_item_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/nested_item_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/nested_item_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/nested_out_of_line_mod/anneal.toml b/anneal/v1/tests/fixtures/nested_out_of_line_mod/anneal.toml similarity index 100% rename from anneal/tests/fixtures/nested_out_of_line_mod/anneal.toml rename to anneal/v1/tests/fixtures/nested_out_of_line_mod/anneal.toml diff --git a/anneal/tests/fixtures/nested_out_of_line_mod/expected.stderr b/anneal/v1/tests/fixtures/nested_out_of_line_mod/expected.stderr similarity index 100% rename from anneal/tests/fixtures/nested_out_of_line_mod/expected.stderr rename to anneal/v1/tests/fixtures/nested_out_of_line_mod/expected.stderr diff --git a/anneal/tests/fixtures/nested_out_of_line_mod/source/Cargo.toml b/anneal/v1/tests/fixtures/nested_out_of_line_mod/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/nested_out_of_line_mod/source/Cargo.toml rename to anneal/v1/tests/fixtures/nested_out_of_line_mod/source/Cargo.toml diff --git a/anneal/tests/fixtures/nested_out_of_line_mod/source/src/hidden.rs b/anneal/v1/tests/fixtures/nested_out_of_line_mod/source/src/hidden.rs similarity index 100% rename from anneal/tests/fixtures/nested_out_of_line_mod/source/src/hidden.rs rename to anneal/v1/tests/fixtures/nested_out_of_line_mod/source/src/hidden.rs diff --git a/anneal/tests/fixtures/nested_out_of_line_mod/source/src/lib.rs b/anneal/v1/tests/fixtures/nested_out_of_line_mod/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/nested_out_of_line_mod/source/src/lib.rs rename to anneal/v1/tests/fixtures/nested_out_of_line_mod/source/src/lib.rs diff --git a/anneal/tests/fixtures/os_arg_limit_exceeded/anneal.toml b/anneal/v1/tests/fixtures/os_arg_limit_exceeded/anneal.toml similarity index 100% rename from anneal/tests/fixtures/os_arg_limit_exceeded/anneal.toml rename to anneal/v1/tests/fixtures/os_arg_limit_exceeded/anneal.toml diff --git a/anneal/tests/fixtures/os_arg_limit_exceeded/expected.stderr b/anneal/v1/tests/fixtures/os_arg_limit_exceeded/expected.stderr similarity index 100% rename from anneal/tests/fixtures/os_arg_limit_exceeded/expected.stderr rename to anneal/v1/tests/fixtures/os_arg_limit_exceeded/expected.stderr diff --git a/anneal/tests/fixtures/os_arg_limit_exceeded/source/Cargo.toml b/anneal/v1/tests/fixtures/os_arg_limit_exceeded/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/os_arg_limit_exceeded/source/Cargo.toml rename to anneal/v1/tests/fixtures/os_arg_limit_exceeded/source/Cargo.toml diff --git a/anneal/tests/fixtures/os_arg_limit_exceeded/source/src/lib.rs b/anneal/v1/tests/fixtures/os_arg_limit_exceeded/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/os_arg_limit_exceeded/source/src/lib.rs rename to anneal/v1/tests/fixtures/os_arg_limit_exceeded/source/src/lib.rs diff --git a/anneal/tests/fixtures/raw_ptr_dst_layout/anneal.toml b/anneal/v1/tests/fixtures/raw_ptr_dst_layout/anneal.toml similarity index 100% rename from anneal/tests/fixtures/raw_ptr_dst_layout/anneal.toml rename to anneal/v1/tests/fixtures/raw_ptr_dst_layout/anneal.toml diff --git a/anneal/tests/fixtures/raw_ptr_dst_layout/expected.stderr b/anneal/v1/tests/fixtures/raw_ptr_dst_layout/expected.stderr similarity index 100% rename from anneal/tests/fixtures/raw_ptr_dst_layout/expected.stderr rename to anneal/v1/tests/fixtures/raw_ptr_dst_layout/expected.stderr diff --git a/anneal/tests/fixtures/raw_ptr_dst_layout/source/Cargo.toml b/anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/raw_ptr_dst_layout/source/Cargo.toml rename to anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/Cargo.toml diff --git a/anneal/tests/fixtures/raw_ptr_dst_layout/source/out.log b/anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/out.log similarity index 100% rename from anneal/tests/fixtures/raw_ptr_dst_layout/source/out.log rename to anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/out.log diff --git a/anneal/tests/fixtures/raw_ptr_dst_layout/source/src/lib.rs b/anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/raw_ptr_dst_layout/source/src/lib.rs rename to anneal/v1/tests/fixtures/raw_ptr_dst_layout/source/src/lib.rs diff --git a/anneal/tests/fixtures/reject_safe_is_safe/anneal.toml b/anneal/v1/tests/fixtures/reject_safe_is_safe/anneal.toml similarity index 100% rename from anneal/tests/fixtures/reject_safe_is_safe/anneal.toml rename to anneal/v1/tests/fixtures/reject_safe_is_safe/anneal.toml diff --git a/anneal/tests/fixtures/reject_safe_is_safe/expected.stderr b/anneal/v1/tests/fixtures/reject_safe_is_safe/expected.stderr similarity index 100% rename from anneal/tests/fixtures/reject_safe_is_safe/expected.stderr rename to anneal/v1/tests/fixtures/reject_safe_is_safe/expected.stderr diff --git a/anneal/tests/fixtures/reject_safe_is_safe/source/Cargo.toml b/anneal/v1/tests/fixtures/reject_safe_is_safe/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/reject_safe_is_safe/source/Cargo.toml rename to anneal/v1/tests/fixtures/reject_safe_is_safe/source/Cargo.toml diff --git a/anneal/tests/fixtures/reject_safe_is_safe/source/src/lib.rs b/anneal/v1/tests/fixtures/reject_safe_is_safe/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/reject_safe_is_safe/source/src/lib.rs rename to anneal/v1/tests/fixtures/reject_safe_is_safe/source/src/lib.rs diff --git a/anneal/tests/fixtures/reject_safe_requires/anneal.toml b/anneal/v1/tests/fixtures/reject_safe_requires/anneal.toml similarity index 100% rename from anneal/tests/fixtures/reject_safe_requires/anneal.toml rename to anneal/v1/tests/fixtures/reject_safe_requires/anneal.toml diff --git a/anneal/tests/fixtures/reject_safe_requires/expected.stderr b/anneal/v1/tests/fixtures/reject_safe_requires/expected.stderr similarity index 100% rename from anneal/tests/fixtures/reject_safe_requires/expected.stderr rename to anneal/v1/tests/fixtures/reject_safe_requires/expected.stderr diff --git a/anneal/tests/fixtures/reject_safe_requires/source/Cargo.toml b/anneal/v1/tests/fixtures/reject_safe_requires/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/reject_safe_requires/source/Cargo.toml rename to anneal/v1/tests/fixtures/reject_safe_requires/source/Cargo.toml diff --git a/anneal/tests/fixtures/reject_safe_requires/source/src/lib.rs b/anneal/v1/tests/fixtures/reject_safe_requires/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/reject_safe_requires/source/src/lib.rs rename to anneal/v1/tests/fixtures/reject_safe_requires/source/src/lib.rs diff --git a/anneal/tests/fixtures/select_bin/anneal.toml b/anneal/v1/tests/fixtures/select_bin/anneal.toml similarity index 100% rename from anneal/tests/fixtures/select_bin/anneal.toml rename to anneal/v1/tests/fixtures/select_bin/anneal.toml diff --git a/anneal/tests/fixtures/select_bin/source/Cargo.toml b/anneal/v1/tests/fixtures/select_bin/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/select_bin/source/Cargo.toml rename to anneal/v1/tests/fixtures/select_bin/source/Cargo.toml diff --git a/anneal/tests/fixtures/select_bin/source/src/lib.rs b/anneal/v1/tests/fixtures/select_bin/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/select_bin/source/src/lib.rs rename to anneal/v1/tests/fixtures/select_bin/source/src/lib.rs diff --git a/anneal/tests/fixtures/select_bin/source/src/main.rs b/anneal/v1/tests/fixtures/select_bin/source/src/main.rs similarity index 100% rename from anneal/tests/fixtures/select_bin/source/src/main.rs rename to anneal/v1/tests/fixtures/select_bin/source/src/main.rs diff --git a/anneal/tests/fixtures/select_lib/anneal.toml b/anneal/v1/tests/fixtures/select_lib/anneal.toml similarity index 100% rename from anneal/tests/fixtures/select_lib/anneal.toml rename to anneal/v1/tests/fixtures/select_lib/anneal.toml diff --git a/anneal/tests/fixtures/select_lib/source/Cargo.toml b/anneal/v1/tests/fixtures/select_lib/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/select_lib/source/Cargo.toml rename to anneal/v1/tests/fixtures/select_lib/source/Cargo.toml diff --git a/anneal/tests/fixtures/select_lib/source/src/lib.rs b/anneal/v1/tests/fixtures/select_lib/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/select_lib/source/src/lib.rs rename to anneal/v1/tests/fixtures/select_lib/source/src/lib.rs diff --git a/anneal/tests/fixtures/select_lib/source/src/main.rs b/anneal/v1/tests/fixtures/select_lib/source/src/main.rs similarity index 100% rename from anneal/tests/fixtures/select_lib/source/src/main.rs rename to anneal/v1/tests/fixtures/select_lib/source/src/main.rs diff --git a/anneal/tests/fixtures/size_of_align_of/anneal.toml b/anneal/v1/tests/fixtures/size_of_align_of/anneal.toml similarity index 100% rename from anneal/tests/fixtures/size_of_align_of/anneal.toml rename to anneal/v1/tests/fixtures/size_of_align_of/anneal.toml diff --git a/anneal/tests/fixtures/size_of_align_of/source/Cargo.toml b/anneal/v1/tests/fixtures/size_of_align_of/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/size_of_align_of/source/Cargo.toml rename to anneal/v1/tests/fixtures/size_of_align_of/source/Cargo.toml diff --git a/anneal/tests/fixtures/size_of_align_of/source/src/lib.rs b/anneal/v1/tests/fixtures/size_of_align_of/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/size_of_align_of/source/src/lib.rs rename to anneal/v1/tests/fixtures/size_of_align_of/source/src/lib.rs diff --git a/anneal/tests/fixtures/sizedness/anneal.toml b/anneal/v1/tests/fixtures/sizedness/anneal.toml similarity index 100% rename from anneal/tests/fixtures/sizedness/anneal.toml rename to anneal/v1/tests/fixtures/sizedness/anneal.toml diff --git a/anneal/tests/fixtures/sizedness/expected.stderr b/anneal/v1/tests/fixtures/sizedness/expected.stderr similarity index 100% rename from anneal/tests/fixtures/sizedness/expected.stderr rename to anneal/v1/tests/fixtures/sizedness/expected.stderr diff --git a/anneal/tests/fixtures/sizedness/source/Cargo.toml b/anneal/v1/tests/fixtures/sizedness/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/sizedness/source/Cargo.toml rename to anneal/v1/tests/fixtures/sizedness/source/Cargo.toml diff --git a/anneal/tests/fixtures/sizedness/source/out.txt b/anneal/v1/tests/fixtures/sizedness/source/out.txt similarity index 100% rename from anneal/tests/fixtures/sizedness/source/out.txt rename to anneal/v1/tests/fixtures/sizedness/source/out.txt diff --git a/anneal/tests/fixtures/sizedness/source/pass/Cargo.toml b/anneal/v1/tests/fixtures/sizedness/source/pass/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/sizedness/source/pass/Cargo.toml rename to anneal/v1/tests/fixtures/sizedness/source/pass/Cargo.toml diff --git a/anneal/tests/fixtures/sizedness/source/pass/src/lib.rs b/anneal/v1/tests/fixtures/sizedness/source/pass/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/sizedness/source/pass/src/lib.rs rename to anneal/v1/tests/fixtures/sizedness/source/pass/src/lib.rs diff --git a/anneal/tests/fixtures/sizedness/source/reject/Cargo.toml b/anneal/v1/tests/fixtures/sizedness/source/reject/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/sizedness/source/reject/Cargo.toml rename to anneal/v1/tests/fixtures/sizedness/source/reject/Cargo.toml diff --git a/anneal/tests/fixtures/sizedness/source/reject/src/lib.rs b/anneal/v1/tests/fixtures/sizedness/source/reject/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/sizedness/source/reject/src/lib.rs rename to anneal/v1/tests/fixtures/sizedness/source/reject/src/lib.rs diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/anneal.toml b/anneal/v1/tests/fixtures/span_empty_unsafe_block/anneal.toml similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/anneal.toml rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/anneal.toml diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/expected.stderr b/anneal/v1/tests/fixtures/span_empty_unsafe_block/expected.stderr similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/expected.stderr rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/expected.stderr diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/mock_charon_output.json b/anneal/v1/tests/fixtures/span_empty_unsafe_block/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/mock_charon_output.json rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/mock_charon_output.json diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/source/Cargo.toml b/anneal/v1/tests/fixtures/span_empty_unsafe_block/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/source/Cargo.toml rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/source/Cargo.toml diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/source/src/lib.rs b/anneal/v1/tests/fixtures/span_empty_unsafe_block/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/source/src/lib.rs rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/source/src/lib.rs diff --git a/anneal/tests/fixtures/span_empty_unsafe_block/source/src/untransformed.rs b/anneal/v1/tests/fixtures/span_empty_unsafe_block/source/src/untransformed.rs similarity index 100% rename from anneal/tests/fixtures/span_empty_unsafe_block/source/src/untransformed.rs rename to anneal/v1/tests/fixtures/span_empty_unsafe_block/source/src/untransformed.rs diff --git a/anneal/tests/fixtures/span_macro_expansion/anneal.toml b/anneal/v1/tests/fixtures/span_macro_expansion/anneal.toml similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/anneal.toml rename to anneal/v1/tests/fixtures/span_macro_expansion/anneal.toml diff --git a/anneal/tests/fixtures/span_macro_expansion/expected.stderr b/anneal/v1/tests/fixtures/span_macro_expansion/expected.stderr similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/expected.stderr rename to anneal/v1/tests/fixtures/span_macro_expansion/expected.stderr diff --git a/anneal/tests/fixtures/span_macro_expansion/mock_charon_output.json b/anneal/v1/tests/fixtures/span_macro_expansion/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/mock_charon_output.json rename to anneal/v1/tests/fixtures/span_macro_expansion/mock_charon_output.json diff --git a/anneal/tests/fixtures/span_macro_expansion/source/Cargo.toml b/anneal/v1/tests/fixtures/span_macro_expansion/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/source/Cargo.toml rename to anneal/v1/tests/fixtures/span_macro_expansion/source/Cargo.toml diff --git a/anneal/tests/fixtures/span_macro_expansion/source/src/lib.rs b/anneal/v1/tests/fixtures/span_macro_expansion/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/source/src/lib.rs rename to anneal/v1/tests/fixtures/span_macro_expansion/source/src/lib.rs diff --git a/anneal/tests/fixtures/span_macro_expansion/source/src/untransformed.rs b/anneal/v1/tests/fixtures/span_macro_expansion/source/src/untransformed.rs similarity index 100% rename from anneal/tests/fixtures/span_macro_expansion/source/src/untransformed.rs rename to anneal/v1/tests/fixtures/span_macro_expansion/source/src/untransformed.rs diff --git a/anneal/tests/fixtures/span_mapping_basic/anneal.toml b/anneal/v1/tests/fixtures/span_mapping_basic/anneal.toml similarity index 100% rename from anneal/tests/fixtures/span_mapping_basic/anneal.toml rename to anneal/v1/tests/fixtures/span_mapping_basic/anneal.toml diff --git a/anneal/tests/fixtures/span_mapping_basic/expected.stderr b/anneal/v1/tests/fixtures/span_mapping_basic/expected.stderr similarity index 100% rename from anneal/tests/fixtures/span_mapping_basic/expected.stderr rename to anneal/v1/tests/fixtures/span_mapping_basic/expected.stderr diff --git a/anneal/tests/fixtures/span_mapping_basic/mock_charon_output.json b/anneal/v1/tests/fixtures/span_mapping_basic/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/span_mapping_basic/mock_charon_output.json rename to anneal/v1/tests/fixtures/span_mapping_basic/mock_charon_output.json diff --git a/anneal/tests/fixtures/span_mapping_basic/source/Cargo.toml b/anneal/v1/tests/fixtures/span_mapping_basic/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/span_mapping_basic/source/Cargo.toml rename to anneal/v1/tests/fixtures/span_mapping_basic/source/Cargo.toml diff --git a/anneal/tests/fixtures/span_mapping_basic/source/src/lib.rs b/anneal/v1/tests/fixtures/span_mapping_basic/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/span_mapping_basic/source/src/lib.rs rename to anneal/v1/tests/fixtures/span_mapping_basic/source/src/lib.rs diff --git a/anneal/tests/fixtures/span_multibyte_offsets/anneal.toml b/anneal/v1/tests/fixtures/span_multibyte_offsets/anneal.toml similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/anneal.toml rename to anneal/v1/tests/fixtures/span_multibyte_offsets/anneal.toml diff --git a/anneal/tests/fixtures/span_multibyte_offsets/expected.stderr b/anneal/v1/tests/fixtures/span_multibyte_offsets/expected.stderr similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/expected.stderr rename to anneal/v1/tests/fixtures/span_multibyte_offsets/expected.stderr diff --git a/anneal/tests/fixtures/span_multibyte_offsets/mock_charon_output.json b/anneal/v1/tests/fixtures/span_multibyte_offsets/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/mock_charon_output.json rename to anneal/v1/tests/fixtures/span_multibyte_offsets/mock_charon_output.json diff --git a/anneal/tests/fixtures/span_multibyte_offsets/source/Cargo.toml b/anneal/v1/tests/fixtures/span_multibyte_offsets/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/source/Cargo.toml rename to anneal/v1/tests/fixtures/span_multibyte_offsets/source/Cargo.toml diff --git a/anneal/tests/fixtures/span_multibyte_offsets/source/src/lib.rs b/anneal/v1/tests/fixtures/span_multibyte_offsets/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/source/src/lib.rs rename to anneal/v1/tests/fixtures/span_multibyte_offsets/source/src/lib.rs diff --git a/anneal/tests/fixtures/span_multibyte_offsets/source/src/untransformed.rs b/anneal/v1/tests/fixtures/span_multibyte_offsets/source/src/untransformed.rs similarity index 100% rename from anneal/tests/fixtures/span_multibyte_offsets/source/src/untransformed.rs rename to anneal/v1/tests/fixtures/span_multibyte_offsets/source/src/untransformed.rs diff --git a/anneal/tests/fixtures/split_artifact/anneal.toml b/anneal/v1/tests/fixtures/split_artifact/anneal.toml similarity index 100% rename from anneal/tests/fixtures/split_artifact/anneal.toml rename to anneal/v1/tests/fixtures/split_artifact/anneal.toml diff --git a/anneal/tests/fixtures/split_artifact/expected.stderr b/anneal/v1/tests/fixtures/split_artifact/expected.stderr similarity index 100% rename from anneal/tests/fixtures/split_artifact/expected.stderr rename to anneal/v1/tests/fixtures/split_artifact/expected.stderr diff --git a/anneal/tests/fixtures/split_artifact/source/Cargo.toml b/anneal/v1/tests/fixtures/split_artifact/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/split_artifact/source/Cargo.toml rename to anneal/v1/tests/fixtures/split_artifact/source/Cargo.toml diff --git a/anneal/tests/fixtures/split_artifact/source/src/lib.rs b/anneal/v1/tests/fixtures/split_artifact/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/split_artifact/source/src/lib.rs rename to anneal/v1/tests/fixtures/split_artifact/source/src/lib.rs diff --git a/anneal/tests/fixtures/split_artifact/source/src/main.rs b/anneal/v1/tests/fixtures/split_artifact/source/src/main.rs similarity index 100% rename from anneal/tests/fixtures/split_artifact/source/src/main.rs rename to anneal/v1/tests/fixtures/split_artifact/source/src/main.rs diff --git a/anneal/tests/fixtures/stale_output/anneal.toml b/anneal/v1/tests/fixtures/stale_output/anneal.toml similarity index 100% rename from anneal/tests/fixtures/stale_output/anneal.toml rename to anneal/v1/tests/fixtures/stale_output/anneal.toml diff --git a/anneal/tests/fixtures/stale_output/source/Cargo.toml b/anneal/v1/tests/fixtures/stale_output/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/stale_output/source/Cargo.toml rename to anneal/v1/tests/fixtures/stale_output/source/Cargo.toml diff --git a/anneal/tests/fixtures/stale_output/source/src/lib.rs b/anneal/v1/tests/fixtures/stale_output/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/stale_output/source/src/lib.rs rename to anneal/v1/tests/fixtures/stale_output/source/src/lib.rs diff --git a/anneal/tests/fixtures/stuck_wps/anneal.toml b/anneal/v1/tests/fixtures/stuck_wps/anneal.toml similarity index 100% rename from anneal/tests/fixtures/stuck_wps/anneal.toml rename to anneal/v1/tests/fixtures/stuck_wps/anneal.toml diff --git a/anneal/tests/fixtures/stuck_wps/expected.stderr b/anneal/v1/tests/fixtures/stuck_wps/expected.stderr similarity index 100% rename from anneal/tests/fixtures/stuck_wps/expected.stderr rename to anneal/v1/tests/fixtures/stuck_wps/expected.stderr diff --git a/anneal/tests/fixtures/stuck_wps/source/Cargo.toml b/anneal/v1/tests/fixtures/stuck_wps/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/stuck_wps/source/Cargo.toml rename to anneal/v1/tests/fixtures/stuck_wps/source/Cargo.toml diff --git a/anneal/tests/fixtures/stuck_wps/source/crates/app/Cargo.toml b/anneal/v1/tests/fixtures/stuck_wps/source/crates/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/stuck_wps/source/crates/app/Cargo.toml rename to anneal/v1/tests/fixtures/stuck_wps/source/crates/app/Cargo.toml diff --git a/anneal/tests/fixtures/stuck_wps/source/crates/app/src/lib.rs b/anneal/v1/tests/fixtures/stuck_wps/source/crates/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/stuck_wps/source/crates/app/src/lib.rs rename to anneal/v1/tests/fixtures/stuck_wps/source/crates/app/src/lib.rs diff --git a/anneal/tests/fixtures/stuck_wps/source/crates/dep/Cargo.toml b/anneal/v1/tests/fixtures/stuck_wps/source/crates/dep/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/stuck_wps/source/crates/dep/Cargo.toml rename to anneal/v1/tests/fixtures/stuck_wps/source/crates/dep/Cargo.toml diff --git a/anneal/tests/fixtures/stuck_wps/source/crates/dep/src/lib.rs b/anneal/v1/tests/fixtures/stuck_wps/source/crates/dep/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/stuck_wps/source/crates/dep/src/lib.rs rename to anneal/v1/tests/fixtures/stuck_wps/source/crates/dep/src/lib.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/anneal.toml b/anneal/v1/tests/fixtures/success_allow_sorry/anneal.toml similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/anneal.toml rename to anneal/v1/tests/fixtures/success_allow_sorry/anneal.toml diff --git a/anneal/tests/fixtures/success_allow_sorry/source/Cargo.toml b/anneal/v1/tests/fixtures/success_allow_sorry/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/Cargo.toml rename to anneal/v1/tests/fixtures/success_allow_sorry/source/Cargo.toml diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/macro_blind_spot/hidden.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/macro_blind_spot/hidden.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/macro_blind_spot/hidden.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/macro_blind_spot/hidden.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/warn_cfg_attr_path/sys_unix.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/warn_cfg_attr_path/sys_unix.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/warn_cfg_attr_path/sys_unix.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/cfg_and_macros/warn_cfg_attr_path/sys_unix.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress/deep_invocation/nested.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress/deep_invocation/nested.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress/deep_invocation/nested.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/hierarchy_and_stress/deep_invocation/nested.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/lib.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/lib.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/lib.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/logic_and_patterns.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/logic_and_patterns.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/logic_and_patterns.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/logic_and_patterns.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/naming_and_imports.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/naming_and_imports.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/naming_and_imports.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/naming_and_imports.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/primitives.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/primitives.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/primitives.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/primitives.rs diff --git a/anneal/tests/fixtures/success_allow_sorry/source/src/types.rs b/anneal/v1/tests/fixtures/success_allow_sorry/source/src/types.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry/source/src/types.rs rename to anneal/v1/tests/fixtures/success_allow_sorry/source/src/types.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/anneal.toml b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/anneal.toml similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/anneal.toml rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/anneal.toml diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/Cargo.toml b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/Cargo.toml rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/Cargo.toml diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/framework.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/framework.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/framework.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/framework.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/lib.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/lib.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/lib.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/logic_and_control.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/logic_and_control.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/logic_and_control.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/logic_and_control.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/macro_checks.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/macro_checks.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/macro_checks.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/macro_checks.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/memory_and_borrows.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/memory_and_borrows.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/memory_and_borrows.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/memory_and_borrows.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/spec_syntax.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/spec_syntax.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/spec_syntax.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/spec_syntax.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/traits_and_impls.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/traits_and_impls.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/traits_and_impls.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/traits_and_impls.rs diff --git a/anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/types_and_data.rs b/anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/types_and_data.rs similarity index 100% rename from anneal/tests/fixtures/success_allow_sorry_is_valid/source/src/types_and_data.rs rename to anneal/v1/tests/fixtures/success_allow_sorry_is_valid/source/src/types_and_data.rs diff --git a/anneal/tests/fixtures/syntax_error/anneal.toml b/anneal/v1/tests/fixtures/syntax_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/syntax_error/anneal.toml rename to anneal/v1/tests/fixtures/syntax_error/anneal.toml diff --git a/anneal/tests/fixtures/syntax_error/expected.stderr b/anneal/v1/tests/fixtures/syntax_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/syntax_error/expected.stderr rename to anneal/v1/tests/fixtures/syntax_error/expected.stderr diff --git a/anneal/tests/fixtures/syntax_error/source/Cargo.toml b/anneal/v1/tests/fixtures/syntax_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/syntax_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/syntax_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/syntax_error/source/src/lib.rs b/anneal/v1/tests/fixtures/syntax_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/syntax_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/syntax_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/target_selection/anneal.toml b/anneal/v1/tests/fixtures/target_selection/anneal.toml similarity index 100% rename from anneal/tests/fixtures/target_selection/anneal.toml rename to anneal/v1/tests/fixtures/target_selection/anneal.toml diff --git a/anneal/tests/fixtures/target_selection/expected.stderr b/anneal/v1/tests/fixtures/target_selection/expected.stderr similarity index 100% rename from anneal/tests/fixtures/target_selection/expected.stderr rename to anneal/v1/tests/fixtures/target_selection/expected.stderr diff --git a/anneal/tests/fixtures/target_selection/source/Cargo.toml b/anneal/v1/tests/fixtures/target_selection/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/target_selection/source/Cargo.toml rename to anneal/v1/tests/fixtures/target_selection/source/Cargo.toml diff --git a/anneal/tests/fixtures/target_selection/source/src/lib.rs b/anneal/v1/tests/fixtures/target_selection/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/target_selection/source/src/lib.rs rename to anneal/v1/tests/fixtures/target_selection/source/src/lib.rs diff --git a/anneal/tests/fixtures/target_selection/source/src/main.rs b/anneal/v1/tests/fixtures/target_selection/source/src/main.rs similarity index 100% rename from anneal/tests/fixtures/target_selection/source/src/main.rs rename to anneal/v1/tests/fixtures/target_selection/source/src/main.rs diff --git a/anneal/tests/fixtures/test_ptr_crate/Cargo.toml b/anneal/v1/tests/fixtures/test_ptr_crate/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/test_ptr_crate/Cargo.toml rename to anneal/v1/tests/fixtures/test_ptr_crate/Cargo.toml diff --git a/anneal/tests/fixtures/test_ptr_crate/src/lib.rs b/anneal/v1/tests/fixtures/test_ptr_crate/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/test_ptr_crate/src/lib.rs rename to anneal/v1/tests/fixtures/test_ptr_crate/src/lib.rs diff --git a/anneal/tests/fixtures/type_features/anneal.toml b/anneal/v1/tests/fixtures/type_features/anneal.toml similarity index 100% rename from anneal/tests/fixtures/type_features/anneal.toml rename to anneal/v1/tests/fixtures/type_features/anneal.toml diff --git a/anneal/tests/fixtures/type_features/expected.stderr b/anneal/v1/tests/fixtures/type_features/expected.stderr similarity index 100% rename from anneal/tests/fixtures/type_features/expected.stderr rename to anneal/v1/tests/fixtures/type_features/expected.stderr diff --git a/anneal/tests/fixtures/type_features/source/Cargo.toml b/anneal/v1/tests/fixtures/type_features/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/type_features/source/Cargo.toml rename to anneal/v1/tests/fixtures/type_features/source/Cargo.toml diff --git a/anneal/tests/fixtures/type_features/source/src/lib.rs b/anneal/v1/tests/fixtures/type_features/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/type_features/source/src/lib.rs rename to anneal/v1/tests/fixtures/type_features/source/src/lib.rs diff --git a/anneal/tests/fixtures/ui_build_script_noise/anneal.toml b/anneal/v1/tests/fixtures/ui_build_script_noise/anneal.toml similarity index 100% rename from anneal/tests/fixtures/ui_build_script_noise/anneal.toml rename to anneal/v1/tests/fixtures/ui_build_script_noise/anneal.toml diff --git a/anneal/tests/fixtures/ui_build_script_noise/expected.stderr b/anneal/v1/tests/fixtures/ui_build_script_noise/expected.stderr similarity index 100% rename from anneal/tests/fixtures/ui_build_script_noise/expected.stderr rename to anneal/v1/tests/fixtures/ui_build_script_noise/expected.stderr diff --git a/anneal/tests/fixtures/ui_build_script_noise/mock_charon_output.json b/anneal/v1/tests/fixtures/ui_build_script_noise/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/ui_build_script_noise/mock_charon_output.json rename to anneal/v1/tests/fixtures/ui_build_script_noise/mock_charon_output.json diff --git a/anneal/tests/fixtures/ui_build_script_noise/source/Cargo.toml b/anneal/v1/tests/fixtures/ui_build_script_noise/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/ui_build_script_noise/source/Cargo.toml rename to anneal/v1/tests/fixtures/ui_build_script_noise/source/Cargo.toml diff --git a/anneal/tests/fixtures/ui_build_script_noise/source/src/lib.rs b/anneal/v1/tests/fixtures/ui_build_script_noise/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/ui_build_script_noise/source/src/lib.rs rename to anneal/v1/tests/fixtures/ui_build_script_noise/source/src/lib.rs diff --git a/anneal/tests/fixtures/ui_hanging_build/anneal.toml b/anneal/v1/tests/fixtures/ui_hanging_build/anneal.toml similarity index 100% rename from anneal/tests/fixtures/ui_hanging_build/anneal.toml rename to anneal/v1/tests/fixtures/ui_hanging_build/anneal.toml diff --git a/anneal/tests/fixtures/ui_hanging_build/expected.stderr b/anneal/v1/tests/fixtures/ui_hanging_build/expected.stderr similarity index 100% rename from anneal/tests/fixtures/ui_hanging_build/expected.stderr rename to anneal/v1/tests/fixtures/ui_hanging_build/expected.stderr diff --git a/anneal/tests/fixtures/ui_hanging_build/source/Cargo.toml b/anneal/v1/tests/fixtures/ui_hanging_build/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/ui_hanging_build/source/Cargo.toml rename to anneal/v1/tests/fixtures/ui_hanging_build/source/Cargo.toml diff --git a/anneal/tests/fixtures/ui_hanging_build/source/build.rs b/anneal/v1/tests/fixtures/ui_hanging_build/source/build.rs similarity index 100% rename from anneal/tests/fixtures/ui_hanging_build/source/build.rs rename to anneal/v1/tests/fixtures/ui_hanging_build/source/build.rs diff --git a/anneal/tests/fixtures/ui_hanging_build/source/src/lib.rs b/anneal/v1/tests/fixtures/ui_hanging_build/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/ui_hanging_build/source/src/lib.rs rename to anneal/v1/tests/fixtures/ui_hanging_build/source/src/lib.rs diff --git a/anneal/tests/fixtures/ui_silent_panic/anneal.toml b/anneal/v1/tests/fixtures/ui_silent_panic/anneal.toml similarity index 100% rename from anneal/tests/fixtures/ui_silent_panic/anneal.toml rename to anneal/v1/tests/fixtures/ui_silent_panic/anneal.toml diff --git a/anneal/tests/fixtures/ui_silent_panic/expected.stderr b/anneal/v1/tests/fixtures/ui_silent_panic/expected.stderr similarity index 100% rename from anneal/tests/fixtures/ui_silent_panic/expected.stderr rename to anneal/v1/tests/fixtures/ui_silent_panic/expected.stderr diff --git a/anneal/tests/fixtures/ui_silent_panic/source/Cargo.toml b/anneal/v1/tests/fixtures/ui_silent_panic/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/ui_silent_panic/source/Cargo.toml rename to anneal/v1/tests/fixtures/ui_silent_panic/source/Cargo.toml diff --git a/anneal/tests/fixtures/ui_silent_panic/source/build.rs b/anneal/v1/tests/fixtures/ui_silent_panic/source/build.rs similarity index 100% rename from anneal/tests/fixtures/ui_silent_panic/source/build.rs rename to anneal/v1/tests/fixtures/ui_silent_panic/source/build.rs diff --git a/anneal/tests/fixtures/ui_silent_panic/source/src/lib.rs b/anneal/v1/tests/fixtures/ui_silent_panic/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/ui_silent_panic/source/src/lib.rs rename to anneal/v1/tests/fixtures/ui_silent_panic/source/src/lib.rs diff --git a/anneal/tests/fixtures/ui_the_flood/anneal.toml b/anneal/v1/tests/fixtures/ui_the_flood/anneal.toml similarity index 100% rename from anneal/tests/fixtures/ui_the_flood/anneal.toml rename to anneal/v1/tests/fixtures/ui_the_flood/anneal.toml diff --git a/anneal/tests/fixtures/ui_the_flood/expected.stderr b/anneal/v1/tests/fixtures/ui_the_flood/expected.stderr similarity index 100% rename from anneal/tests/fixtures/ui_the_flood/expected.stderr rename to anneal/v1/tests/fixtures/ui_the_flood/expected.stderr diff --git a/anneal/tests/fixtures/ui_the_flood/mock_charon_output.json b/anneal/v1/tests/fixtures/ui_the_flood/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/ui_the_flood/mock_charon_output.json rename to anneal/v1/tests/fixtures/ui_the_flood/mock_charon_output.json diff --git a/anneal/tests/fixtures/ui_the_flood/source/Cargo.toml b/anneal/v1/tests/fixtures/ui_the_flood/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/ui_the_flood/source/Cargo.toml rename to anneal/v1/tests/fixtures/ui_the_flood/source/Cargo.toml diff --git a/anneal/tests/fixtures/ui_the_flood/source/src/lib.rs b/anneal/v1/tests/fixtures/ui_the_flood/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/ui_the_flood/source/src/lib.rs rename to anneal/v1/tests/fixtures/ui_the_flood/source/src/lib.rs diff --git a/anneal/tests/fixtures/ui_visual_ghosting/anneal.toml b/anneal/v1/tests/fixtures/ui_visual_ghosting/anneal.toml similarity index 100% rename from anneal/tests/fixtures/ui_visual_ghosting/anneal.toml rename to anneal/v1/tests/fixtures/ui_visual_ghosting/anneal.toml diff --git a/anneal/tests/fixtures/ui_visual_ghosting/expected.stderr b/anneal/v1/tests/fixtures/ui_visual_ghosting/expected.stderr similarity index 100% rename from anneal/tests/fixtures/ui_visual_ghosting/expected.stderr rename to anneal/v1/tests/fixtures/ui_visual_ghosting/expected.stderr diff --git a/anneal/tests/fixtures/ui_visual_ghosting/mock_charon_output.json b/anneal/v1/tests/fixtures/ui_visual_ghosting/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/ui_visual_ghosting/mock_charon_output.json rename to anneal/v1/tests/fixtures/ui_visual_ghosting/mock_charon_output.json diff --git a/anneal/tests/fixtures/ui_visual_ghosting/source/Cargo.toml b/anneal/v1/tests/fixtures/ui_visual_ghosting/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/ui_visual_ghosting/source/Cargo.toml rename to anneal/v1/tests/fixtures/ui_visual_ghosting/source/Cargo.toml diff --git a/anneal/tests/fixtures/ui_visual_ghosting/source/src/lib.rs b/anneal/v1/tests/fixtures/ui_visual_ghosting/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/ui_visual_ghosting/source/src/lib.rs rename to anneal/v1/tests/fixtures/ui_visual_ghosting/source/src/lib.rs diff --git a/anneal/tests/fixtures/unions/anneal.toml b/anneal/v1/tests/fixtures/unions/anneal.toml similarity index 100% rename from anneal/tests/fixtures/unions/anneal.toml rename to anneal/v1/tests/fixtures/unions/anneal.toml diff --git a/anneal/tests/fixtures/unions/expected.stderr b/anneal/v1/tests/fixtures/unions/expected.stderr similarity index 100% rename from anneal/tests/fixtures/unions/expected.stderr rename to anneal/v1/tests/fixtures/unions/expected.stderr diff --git a/anneal/tests/fixtures/unions/source/Cargo.toml b/anneal/v1/tests/fixtures/unions/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/unions/source/Cargo.toml rename to anneal/v1/tests/fixtures/unions/source/Cargo.toml diff --git a/anneal/tests/fixtures/unions/source/src/lib.rs b/anneal/v1/tests/fixtures/unions/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/unions/source/src/lib.rs rename to anneal/v1/tests/fixtures/unions/source/src/lib.rs diff --git a/anneal/tests/fixtures/unsound_is_valid_error/anneal.toml b/anneal/v1/tests/fixtures/unsound_is_valid_error/anneal.toml similarity index 100% rename from anneal/tests/fixtures/unsound_is_valid_error/anneal.toml rename to anneal/v1/tests/fixtures/unsound_is_valid_error/anneal.toml diff --git a/anneal/tests/fixtures/unsound_is_valid_error/expected.stderr b/anneal/v1/tests/fixtures/unsound_is_valid_error/expected.stderr similarity index 100% rename from anneal/tests/fixtures/unsound_is_valid_error/expected.stderr rename to anneal/v1/tests/fixtures/unsound_is_valid_error/expected.stderr diff --git a/anneal/tests/fixtures/unsound_is_valid_error/source/Cargo.toml b/anneal/v1/tests/fixtures/unsound_is_valid_error/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/unsound_is_valid_error/source/Cargo.toml rename to anneal/v1/tests/fixtures/unsound_is_valid_error/source/Cargo.toml diff --git a/anneal/tests/fixtures/unsound_is_valid_error/source/src/lib.rs b/anneal/v1/tests/fixtures/unsound_is_valid_error/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/unsound_is_valid_error/source/src/lib.rs rename to anneal/v1/tests/fixtures/unsound_is_valid_error/source/src/lib.rs diff --git a/anneal/tests/fixtures/verify_is_valid_macro/anneal.toml b/anneal/v1/tests/fixtures/verify_is_valid_macro/anneal.toml similarity index 100% rename from anneal/tests/fixtures/verify_is_valid_macro/anneal.toml rename to anneal/v1/tests/fixtures/verify_is_valid_macro/anneal.toml diff --git a/anneal/tests/fixtures/verify_is_valid_macro/source/Cargo.toml b/anneal/v1/tests/fixtures/verify_is_valid_macro/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/verify_is_valid_macro/source/Cargo.toml rename to anneal/v1/tests/fixtures/verify_is_valid_macro/source/Cargo.toml diff --git a/anneal/tests/fixtures/verify_is_valid_macro/source/src/lib.rs b/anneal/v1/tests/fixtures/verify_is_valid_macro/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/verify_is_valid_macro/source/src/lib.rs rename to anneal/v1/tests/fixtures/verify_is_valid_macro/source/src/lib.rs diff --git a/anneal/tests/fixtures/warnings_vs_errors/anneal.toml b/anneal/v1/tests/fixtures/warnings_vs_errors/anneal.toml similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/anneal.toml rename to anneal/v1/tests/fixtures/warnings_vs_errors/anneal.toml diff --git a/anneal/tests/fixtures/warnings_vs_errors/expected.stderr b/anneal/v1/tests/fixtures/warnings_vs_errors/expected.stderr similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/expected.stderr rename to anneal/v1/tests/fixtures/warnings_vs_errors/expected.stderr diff --git a/anneal/tests/fixtures/warnings_vs_errors/mock_charon_output.json b/anneal/v1/tests/fixtures/warnings_vs_errors/mock_charon_output.json similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/mock_charon_output.json rename to anneal/v1/tests/fixtures/warnings_vs_errors/mock_charon_output.json diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/Cargo.toml b/anneal/v1/tests/fixtures/warnings_vs_errors/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/Cargo.toml rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/Cargo.toml diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/warnings_vs_errors/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/crates/utils/src/lib.rs diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/src/lib.rs b/anneal/v1/tests/fixtures/warnings_vs_errors/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/src/lib.rs rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/src/lib.rs diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/src/macros.rs b/anneal/v1/tests/fixtures/warnings_vs_errors/source/src/macros.rs similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/src/macros.rs rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/src/macros.rs diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/src/rewritten.rs b/anneal/v1/tests/fixtures/warnings_vs_errors/source/src/rewritten.rs similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/src/rewritten.rs rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/src/rewritten.rs diff --git a/anneal/tests/fixtures/warnings_vs_errors/source/src/symlinked.rs b/anneal/v1/tests/fixtures/warnings_vs_errors/source/src/symlinked.rs similarity index 100% rename from anneal/tests/fixtures/warnings_vs_errors/source/src/symlinked.rs rename to anneal/v1/tests/fixtures/warnings_vs_errors/source/src/symlinked.rs diff --git a/anneal/tests/fixtures/weird_functions/anneal.toml b/anneal/v1/tests/fixtures/weird_functions/anneal.toml similarity index 100% rename from anneal/tests/fixtures/weird_functions/anneal.toml rename to anneal/v1/tests/fixtures/weird_functions/anneal.toml diff --git a/anneal/tests/fixtures/weird_functions/expected.stderr b/anneal/v1/tests/fixtures/weird_functions/expected.stderr similarity index 100% rename from anneal/tests/fixtures/weird_functions/expected.stderr rename to anneal/v1/tests/fixtures/weird_functions/expected.stderr diff --git a/anneal/tests/fixtures/weird_functions/source/Cargo.toml b/anneal/v1/tests/fixtures/weird_functions/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/weird_functions/source/Cargo.toml rename to anneal/v1/tests/fixtures/weird_functions/source/Cargo.toml diff --git a/anneal/tests/fixtures/weird_functions/source/src/lib.rs b/anneal/v1/tests/fixtures/weird_functions/source/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/weird_functions/source/src/lib.rs rename to anneal/v1/tests/fixtures/weird_functions/source/src/lib.rs diff --git a/anneal/tests/fixtures/workspace_path_dep/args.txt b/anneal/v1/tests/fixtures/workspace_path_dep/args.txt similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/args.txt rename to anneal/v1/tests/fixtures/workspace_path_dep/args.txt diff --git a/anneal/tests/fixtures/workspace_path_dep/source/Cargo.toml b/anneal/v1/tests/fixtures/workspace_path_dep/source/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/source/Cargo.toml rename to anneal/v1/tests/fixtures/workspace_path_dep/source/Cargo.toml diff --git a/anneal/tests/fixtures/workspace_path_dep/source/crates/app/Cargo.toml b/anneal/v1/tests/fixtures/workspace_path_dep/source/crates/app/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/source/crates/app/Cargo.toml rename to anneal/v1/tests/fixtures/workspace_path_dep/source/crates/app/Cargo.toml diff --git a/anneal/tests/fixtures/workspace_path_dep/source/crates/app/src/lib.rs b/anneal/v1/tests/fixtures/workspace_path_dep/source/crates/app/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/source/crates/app/src/lib.rs rename to anneal/v1/tests/fixtures/workspace_path_dep/source/crates/app/src/lib.rs diff --git a/anneal/tests/fixtures/workspace_path_dep/source/crates/utils/Cargo.toml b/anneal/v1/tests/fixtures/workspace_path_dep/source/crates/utils/Cargo.toml similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/source/crates/utils/Cargo.toml rename to anneal/v1/tests/fixtures/workspace_path_dep/source/crates/utils/Cargo.toml diff --git a/anneal/tests/fixtures/workspace_path_dep/source/crates/utils/src/lib.rs b/anneal/v1/tests/fixtures/workspace_path_dep/source/crates/utils/src/lib.rs similarity index 100% rename from anneal/tests/fixtures/workspace_path_dep/source/crates/utils/src/lib.rs rename to anneal/v1/tests/fixtures/workspace_path_dep/source/crates/utils/src/lib.rs diff --git a/anneal/tests/integration.rs b/anneal/v1/tests/integration.rs similarity index 100% rename from anneal/tests/integration.rs rename to anneal/v1/tests/integration.rs diff --git a/anneal/tests/ui.rs b/anneal/v1/tests/ui.rs similarity index 100% rename from anneal/tests/ui.rs rename to anneal/v1/tests/ui.rs diff --git a/anneal/tests/ui/fail_precondition.rs b/anneal/v1/tests/ui/fail_precondition.rs similarity index 100% rename from anneal/tests/ui/fail_precondition.rs rename to anneal/v1/tests/ui/fail_precondition.rs diff --git a/anneal/tests/ui/fail_precondition.stderr b/anneal/v1/tests/ui/fail_precondition.stderr similarity index 100% rename from anneal/tests/ui/fail_precondition.stderr rename to anneal/v1/tests/ui/fail_precondition.stderr diff --git a/anneal/tests/ui/fail_syntax.rs b/anneal/v1/tests/ui/fail_syntax.rs similarity index 100% rename from anneal/tests/ui/fail_syntax.rs rename to anneal/v1/tests/ui/fail_syntax.rs diff --git a/anneal/tests/ui/fail_syntax.stderr b/anneal/v1/tests/ui/fail_syntax.stderr similarity index 100% rename from anneal/tests/ui/fail_syntax.stderr rename to anneal/v1/tests/ui/fail_syntax.stderr diff --git a/anneal/tests/ui/pass_simple.rs b/anneal/v1/tests/ui/pass_simple.rs similarity index 100% rename from anneal/tests/ui/pass_simple.rs rename to anneal/v1/tests/ui/pass_simple.rs diff --git a/anneal/tools/check-release-flow-dry-run.sh b/anneal/v1/tools/check-release-flow-dry-run.sh similarity index 83% rename from anneal/tools/check-release-flow-dry-run.sh rename to anneal/v1/tools/check-release-flow-dry-run.sh index bab19fee67..5a26e47b10 100644 --- a/anneal/tools/check-release-flow-dry-run.sh +++ b/anneal/v1/tools/check-release-flow-dry-run.sh @@ -28,13 +28,13 @@ cd "$WORKTREE" ./ci/release_anneal_version.sh "$VERSION" -python3 anneal/tools/check-release-pr-files.py \ +python3 anneal/v1/tools/check-release-pr-files.py \ --context "Release dry-run version bump" \ --include-untracked \ - --allowed anneal/Cargo.lock \ - --allowed anneal/Cargo.toml \ - --allowed anneal/README.md \ - --required anneal/Cargo.toml + --allowed anneal/v1/Cargo.lock \ + --allowed anneal/v1/Cargo.toml \ + --allowed anneal/v1/README.md \ + --required anneal/v1/Cargo.toml git diff --binary > "$PATCH" if [ ! -s "$PATCH" ]; then @@ -47,15 +47,15 @@ git clean -fdx >/dev/null git apply --check "$PATCH" git apply "$PATCH" -python3 anneal/tools/check-release-pr-files.py \ +python3 anneal/v1/tools/check-release-pr-files.py \ --context "Release dry-run applied source patch" \ --include-untracked \ - --allowed anneal/Cargo.lock \ - --allowed anneal/Cargo.toml \ - --allowed anneal/README.md \ - --required anneal/Cargo.toml + --allowed anneal/v1/Cargo.lock \ + --allowed anneal/v1/Cargo.toml \ + --allowed anneal/v1/README.md \ + --required anneal/v1/Cargo.toml -mkdir -p anneal/release-metadata +mkdir -p anneal/v1/release-metadata for target in linux-x86_64 linux-aarch64 macos-x86_64 macos-aarch64; do case "$target" in linux-x86_64) @@ -82,7 +82,7 @@ for target in linux-x86_64 linux-aarch64 macos-x86_64 macos-aarch64; do sha256="$(python3 -c 'import hashlib, sys; print(hashlib.sha256(sys.argv[1].encode()).hexdigest())' "$target")" url="https://github.com/google/zerocopy/releases/download/${TAG_NAME}/anneal-toolchain-${target}.tar.zst" - cat > "anneal/release-metadata/${target}.json" < "anneal/v1/release-metadata/${target}.json" < None: - status = " M anneal/Cargo.toml\n?? anneal/release-metadata/linux.json\nR old/path -> anneal/README.md\n" + status = " M anneal/v1/Cargo.toml\n?? anneal/v1/release-metadata/linux.json\nR old/path -> anneal/v1/README.md\n" self.assertEqual( check_release_pr_files.parse_porcelain_status_paths(status), - ["anneal/Cargo.toml", "anneal/release-metadata/linux.json", "old/path", "anneal/README.md"], + ["anneal/v1/Cargo.toml", "anneal/v1/release-metadata/linux.json", "old/path", "anneal/v1/README.md"], ) def test_validation_catches_unexpected_and_missing_files(self) -> None: errors = check_release_pr_files.validation_errors( - ["anneal/Cargo.toml", "anneal/release-metadata/linux.json"], - ["anneal/Cargo.toml", "anneal/Cargo.lock", "anneal/README.md"], - ["anneal/Cargo.toml", "anneal/README.md"], + ["anneal/v1/Cargo.toml", "anneal/v1/release-metadata/linux.json"], + ["anneal/v1/Cargo.toml", "anneal/v1/Cargo.lock", "anneal/v1/README.md"], + ["anneal/v1/Cargo.toml", "anneal/v1/README.md"], ) self.assertEqual(len(errors), 2) - self.assertIn("anneal/release-metadata/linux.json", errors[0]) - self.assertIn("anneal/README.md", errors[1]) + self.assertIn("anneal/v1/release-metadata/linux.json", errors[0]) + self.assertIn("anneal/v1/README.md", errors[1]) if __name__ == "__main__": diff --git a/anneal/tools/update-exocrate-metadata.py b/anneal/v1/tools/update-exocrate-metadata.py similarity index 97% rename from anneal/tools/update-exocrate-metadata.py rename to anneal/v1/tools/update-exocrate-metadata.py index f8e2fc4516..96c4cdde80 100755 --- a/anneal/tools/update-exocrate-metadata.py +++ b/anneal/v1/tools/update-exocrate-metadata.py @@ -8,7 +8,7 @@ # This file may not be copied, modified, or distributed except according to # those terms. -"""Update anneal/Cargo.toml's exocrate archive URLs and hashes.""" +"""Update anneal/v1/Cargo.toml's exocrate archive URLs and hashes.""" import argparse import json @@ -124,7 +124,7 @@ def update_manifest(cargo_toml: Path, metadata: dict[tuple[str, str], dict[str, def main() -> None: parser = argparse.ArgumentParser() - parser.add_argument("--cargo-toml", default="anneal/Cargo.toml", type=Path) + parser.add_argument("--cargo-toml", default="anneal/v1/Cargo.toml", type=Path) parser.add_argument("--metadata-dir", type=Path) parser.add_argument("--metadata", action="append", default=[], type=Path) parser.add_argument("--expected-release-tag") diff --git a/anneal/v2/Cargo.toml b/anneal/v2/Cargo.toml deleted file mode 100644 index e91b731c5c..0000000000 --- a/anneal/v2/Cargo.toml +++ /dev/null @@ -1,69 +0,0 @@ -[workspace] -members = ["."] - -[features] -# Enables tests that assume a prebuilt exocrate archive. -exocrate_tests = [] - -[package] -name = "cargo-anneal" -edition = "2024" -version = "0.1.0-alpha.22" -description = "Formally verify that your safety comments are correct." -categories = [ - "development-tools::cargo-plugins", - "development-tools::testing", - "compilers", - "mathematics", - "security", -] -keywords = ["verification", "cargo", "plugin", "unsafe", "lean"] -license = "BSD-2-Clause OR Apache-2.0 OR MIT" -repository = "https://github.com/google/zerocopy/tree/main/anneal" -publish = true - -exclude = [".*", "testdata"] - -# FIXME: Replace these placeholder archive URLs and hashes before publishing -# this crate; `cargo anneal setup` uses this metadata by default when callers -# do not provide a local archive. -[package.metadata.exocrate.linux.x86_64] -sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -url = "https://example.com/linux-x86_64.tar.zst" - -[package.metadata.exocrate.macos.x86_64] -sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -url = "https://example.com/macos-x86_64.tar.zst" - -[package.metadata.exocrate.linux.aarch64] -sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -url = "https://example.com/linux-aarch64.tar.zst" - -[package.metadata.exocrate.macos.aarch64] -sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" -url = "https://example.com/macos-aarch64.tar.zst" - -[dependencies] -exocrate = { path = "../../exocrate" } -toml_const = "1.3.0" -clap = { version = "4.5", features = ["derive"] } -clap-cargo = { version = "0.18.3", features = ["cargo_metadata"] } -env_logger = "0.11" -log = "0.4" -anyhow = "1.0.102" -cargo_metadata = "0.23.1" -miette = { version = "7.6.0", features = ["derive", "fancy"] } -thiserror = "2.0.18" -serde_json = "1.0.149" -serde = { version = "1.0.228", features = ["derive"] } -indicatif = { version = "0.18.4", features = ["improved_unicode"] } -fs2 = "0.4" -walkdir = "2.5.0" -sha2 = "0.10" -tempfile = "3.27.0" -rayon = "1.11.0" -# `tag` is `main` branch HEAD on 2026-06-03. -charon_lib = { package = "charon", git = "https://github.com/AeneasVerif/charon.git", tag = "nightly-2026.06.03", default-features = false } - -[dev-dependencies] -pathdiff = "0.2" diff --git a/anneal/v2/src/main.rs b/anneal/v2/src/main.rs deleted file mode 100644 index b947700606..0000000000 --- a/anneal/v2/src/main.rs +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright 2026 The Fuchsia Authors -// -// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 -// , or the MIT -// license , at your option. -// This file may not be copied, modified, or distributed except according to -// those terms. - -use clap::Parser as _; - -#[allow(dead_code)] -mod resolve; -#[allow(dead_code)] -mod scanner; -#[allow(dead_code)] -mod setup; -#[allow(dead_code)] -mod util; - -/// Anneal -#[derive(clap::Parser, Debug)] -#[command(name = "cargo-anneal", version, about, long_about = None)] -struct Cli { - #[command(subcommand)] - command: Commands, -} - -#[derive(clap::Subcommand, Debug)] -enum Commands { - /// Setup Anneal dependencies - Setup(SetupArgs), -} - -#[derive(clap::Parser, Debug)] -pub struct SetupArgs { - /// Path to a local dependency archive to use instead of downloading. - #[arg(long, value_name = "path-to-local-archive")] - pub local_archive: Option, -} - -exocrate::config! { - const CONFIG: Config = Config { - rel_dir_path: [".anneal", "toolchain"], - versioned_files: &["../Cargo.toml", "../Cargo.lock"], - }; -} - -exocrate::parse_remote_archive! { - const REMOTE: RemoteArchive = "Cargo.toml" [ - (linux, x86_64), - (macos, x86_64), - (linux, aarch64), - (macos, aarch64), - ]; -} - -fn setup_installation_dir(args: SetupArgs) -> std::path::PathBuf { - let location = if std::env::var("__ANNEAL_LOCAL_DEV").is_ok() { - exocrate::Location::LocalDev - } else { - exocrate::Location::UserGlobal - }; - let source = match args.local_archive { - Some(local_archive) => exocrate::Source::Local(local_archive), - None => exocrate::Source::Remote(REMOTE), - }; - - let (installation_dir, _) = CONFIG - .resolve_installation_dir_or_install(location, source) - // FIXME: Implement unified error reporting (e.g., via `anyhow`). - .expect("failed to resolve-or-install dependencies"); - installation_dir -} - -fn setup(args: SetupArgs) { - let installation_dir = setup_installation_dir(args); - log::info!("anneal toolchain is installed at {:?}", installation_dir); -} - -fn main() { - // Suppressing timestamps removes a source of nondeterminism that is - // difficult to work around in integration tests. - env_logger::builder().format_timestamp(None).init(); - - let mut args_iter = std::env::args_os().peekable(); - let bin_name = args_iter.next().unwrap_or_else(|| "cargo-anneal".into()); - // If we're being run as a cargo plugin, the second argument will be "anneal". - if args_iter.peek().is_some_and(|arg| arg == "anneal") { - args_iter.next(); - } - let args = Cli::parse_from(std::iter::once(bin_name).chain(args_iter)); - - match args.command { - Commands::Setup(args) => setup(args), - } -} - -#[cfg(test)] -mod tests { - #[cfg(feature = "exocrate_tests")] - mod exocrate_tests { - use std::{ - fs, io, - path::{Path, PathBuf}, - process::Command, - sync::OnceLock, - }; - - use serde_json::{Value, json}; - - const LOCAL_ARCHIVE: &str = "target/anneal-exocrate.tar.zst"; - static INSTALLATION_DIR: OnceLock = OnceLock::new(); - - #[test] - fn test_setup() { - install_local_archive(); - } - - #[test] - fn test_archive_lake_cache_reuse() { - let installation_dir = install_local_archive(); - let temp = tempfile::Builder::new() - .prefix("anneal-v2-archive-cache-reuse-") - .tempdir() - .expect("failed to create archive cache reuse tempdir"); - assert_archive_lake_cache_reuse(&installation_dir, temp.path()) - .expect("archive Lake cache reuse test failed"); - } - - fn install_local_archive() -> PathBuf { - // ASSUMPTION: The CI dependency builder downloads the Nix-built - // archive artifact to this path before running v2 tests. - INSTALLATION_DIR - .get_or_init(|| { - super::super::setup_installation_dir(super::super::SetupArgs { - local_archive: Some(LOCAL_ARCHIVE.into()), - }) - }) - .clone() - } - - fn assert_archive_lake_cache_reuse( - toolchain_root: &Path, - temp_root: &Path, - ) -> Result<(), Box> { - let aeneas_root = toolchain_root.join("aeneas"); - let aeneas_lean = aeneas_root.join("backends/lean"); - let lean_root = toolchain_root.join("lean"); - let workspace = temp_root.join("generated-workspace"); - - assert_no_write_bits(&aeneas_root)?; - - fs::create_dir_all(workspace.join("generated"))?; - fs::copy(aeneas_lean.join("lean-toolchain"), workspace.join("lean-toolchain"))?; - fs::write(workspace.join("generated/Generated.lean"), "import Aeneas\n")?; - fs::write( - workspace.join("lakefile.lean"), - format!( - r#"import Lake -open Lake DSL - -require aeneas from "{}" - -package anneal_verification - -@[default_target] -lean_lib Generated where - srcDir := "generated" - roots := #[`Generated] -"#, - lake_string(&aeneas_lean) - ), - )?; - write_relative_archive_manifest(&workspace, &aeneas_lean)?; - - // The Nix archive must support fresh generated workspaces without - // reconfiguring packages or rebuilding read-only Lake artifacts. - run_lake_archive_command( - &workspace, - &lean_root, - &["--keep-toolchain", "--old", "build", "Generated"], - )?; - run_lake_archive_command( - &workspace, - &lean_root, - &["--keep-toolchain", "env", "lean", "--json", "generated/Generated.lean"], - )?; - - Ok(()) - } - - fn assert_no_write_bits(root: &Path) -> Result<(), Box> { - let metadata = fs::symlink_metadata(root)?; - if metadata.file_type().is_symlink() { - return Ok(()); - } - if has_write_bits(&metadata.permissions()) { - panic!("archive path should be read-only: {}", root.display()); - } - if metadata.is_dir() { - for entry in fs::read_dir(root)? { - assert_no_write_bits(&entry?.path())?; - } - } - Ok(()) - } - - #[cfg(unix)] - fn has_write_bits(permissions: &fs::Permissions) -> bool { - use std::os::unix::fs::PermissionsExt as _; - permissions.mode() & 0o222 != 0 - } - - #[cfg(not(unix))] - fn has_write_bits(permissions: &fs::Permissions) -> bool { - !permissions.readonly() - } - - fn write_relative_archive_manifest( - workspace: &Path, - aeneas_lean: &Path, - ) -> Result<(), Box> { - let aeneas_lean = fs::canonicalize(aeneas_lean)?; - let workspace = fs::canonicalize(workspace)?; - let manifest_path = aeneas_lean.join("lake-manifest.json"); - let manifest: Value = serde_json::from_reader(fs::File::open(&manifest_path)?)?; - let aeneas_packages = - manifest.get("packages").and_then(Value::as_array).ok_or_else(|| { - invalid_data(format!( - "Aeneas Lake manifest {} is missing packages", - manifest_path.display() - )) - })?; - - let aeneas_dir = relative_manifest_string(&aeneas_lean, &workspace)?; - let mut packages = vec![json!({ - "type": "path", - "name": "aeneas", - "dir": aeneas_dir, - "inherited": false, - })]; - - for entry in aeneas_packages { - let mut entry = entry.as_object().cloned().ok_or_else(|| { - invalid_data("Aeneas Lake manifest package entry is not an object") - })?; - let package_type = entry.get("type").and_then(Value::as_str).ok_or_else(|| { - invalid_data("Aeneas Lake manifest package entry is missing type") - })?; - if package_type != "path" { - return Err(invalid_data(format!( - "Aeneas Lake manifest package entry is {package_type:?}, not a path dependency" - )) - .into()); - } - let package_dir = entry.get("dir").and_then(Value::as_str).ok_or_else(|| { - invalid_data("Aeneas Lake manifest package entry is missing dir") - })?; - let package_dir = Path::new(package_dir); - let package_dir = if package_dir.is_absolute() { - package_dir.to_path_buf() - } else { - aeneas_lean.join(package_dir) - }; - let package_dir = fs::canonicalize(package_dir)?; - entry.insert( - "dir".to_string(), - json!(relative_manifest_string(&package_dir, &workspace)?), - ); - entry.insert("inherited".to_string(), json!(true)); - packages.push(Value::Object(entry)); - } - - let manifest = json!({ - "version": "1.2.0", - "packagesDir": ".lake/packages", - "packages": packages, - "name": "anneal_verification", - "lakeDir": ".lake", - "fixedToolchain": false, - }); - fs::write( - workspace.join("lake-manifest.json"), - format!("{}\n", serde_json::to_string_pretty(&manifest)?), - )?; - Ok(()) - } - - fn relative_manifest_string( - path: &Path, - base: &Path, - ) -> Result> { - let path = pathdiff::diff_paths(path, base).ok_or_else(|| { - invalid_data(format!( - "failed to compute relative path from {} to {}", - base.display(), - path.display() - )) - })?; - Ok(path.to_string_lossy().into_owned()) - } - - fn lake_string(path: &Path) -> String { - path.to_string_lossy().replace('\\', "\\\\").replace('"', "\\\"") - } - - fn run_lake_archive_command( - workspace: &Path, - lean_root: &Path, - args: &[&str], - ) -> Result<(), Box> { - let lean_bin = lean_root.join("bin"); - let mut cmd = Command::new(lean_bin.join("lake")); - cmd.args(args).current_dir(workspace).env_clear(); - - let lib_var = - if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" } else { "LD_LIBRARY_PATH" }; - cmd.env( - lib_var, - std::env::join_paths([lean_root.join("lib"), lean_root.join("lib/lean")])?, - ); - - let output = cmd.output()?; - if !output.status.success() { - return Err(io::Error::other(format!( - "lake {:?} failed with status {}\nstdout:\n{}\nstderr:\n{}", - args, - output.status, - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )) - .into()); - } - Ok(()) - } - - fn invalid_data(message: impl Into) -> io::Error { - io::Error::new(io::ErrorKind::InvalidData, message.into()) - } - } -} diff --git a/anneal/v2/src/scanner.rs b/anneal/v2/src/scanner.rs deleted file mode 100644 index 7b4884c9ac..0000000000 --- a/anneal/v2/src/scanner.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2026 The Fuchsia Authors -// -// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 -// , or the MIT -// license , at your option. -// This file may not be copied, modified, or distributed except according to -// those terms. - -use sha2::Digest as _; - -/// Represents a compilation target (artifact) that needs to be processed. -/// -/// Charon compiles the entire target to generate LLBC files. The generated -/// LLBC is the source of truth for processing Anneal annotations that affect -/// Aeneas code generation. -#[derive(Clone, Debug)] -pub struct AnnealArtifact { - pub name: crate::resolve::AnnealTargetName, - pub target_kind: crate::resolve::AnnealTargetKind, - /// The path to the crate's `Cargo.toml`. - pub manifest_path: std::path::PathBuf, -} - -impl From<&crate::resolve::AnnealTarget> for AnnealArtifact { - fn from(target: &crate::resolve::AnnealTarget) -> Self { - Self { - name: target.name.clone(), - target_kind: target.kind, - manifest_path: target.manifest_path.clone(), - } - } -} - -impl AnnealArtifact { - /// Returns a unique, Lean-compatible artifact slug. - /// - /// Charon uses the slug as the file stem for the target's emitted LLBC - /// file. Later Aeneas/Lean stages can reuse the same Lean-compatible stem - /// when associating generated Lean code with this artifact. The slug is - /// guaranteed to be a valid Lean identifier (no hyphens), and is unique - /// based on the manifest path, target name, and target kind. - pub fn artifact_slug(&self) -> String { - fn hash(data: &[u8]) -> u64 { - // Use SHA-256 not for security but rather stability; Rust's - // `DefaultHasher` doesn't guarantee stability even across runs of - // the same binary. - let mut hasher = sha2::Sha256::new(); - hasher.update(data); - let result = hasher.finalize(); - let mut bytes = [0u8; 8]; - bytes.copy_from_slice(&result[0..8]); - u64::from_le_bytes(bytes) - } - - // Compute `hash([hash(manifest_path), hash(target_name), hash(target_kind)])` to - // distinguish between e.g. (manifest_path, target_name) = ("abc", "def") and - // ("ab", "cdef"), which would hash identically if we just hashed their - // concatenation. - let h0 = hash(self.manifest_path.as_os_str().as_encoded_bytes()); - let h1 = hash(self.name.target_name.as_bytes()); - let h2 = hash(&[self.target_kind as u8]); - let hashes = [h0, h1, h2]; - let h = hash(&hashes.map(u64::to_ne_bytes).concat()); - - // Converts kebab-case -> PascalCase. - // We convert both package and target names to PascalCase to ensure - // the generated Lean module name is a valid and idiomatic Lean - // identifier, matching Aeneas's output format. - let to_pascal = |s: &str| { - s.split(['-', '_']) - .map(|segment| { - let mut chars = segment.chars(); - match chars.next() { - None => String::new(), - Some(f) => f.to_uppercase().collect::() + chars.as_str(), - } - }) - .collect::() - }; - - let pkg = to_pascal(self.name.package_name.as_str()); - let target = to_pascal(&self.name.target_name); - - // We use the hash to ensure uniqueness even if our prior `to_pascal` - // mapping caused a collision. - format!("{}{}{:08x}", pkg, target, h) - } - - /// Returns the name of the `.llbc` file to use for this artifact. - pub fn llbc_file_name(&self) -> String { - format!("{}.llbc", self.artifact_slug()) - } - - /// Returns the absolute path to the .llbc file. - /// - /// This method requires [`crate::resolve::LockedRoots`] to ensure that the caller holds the - /// build lock before accessing the build artifact path. - pub fn llbc_path(&self, roots: &crate::resolve::LockedRoots) -> std::path::PathBuf { - roots.llbc_root().join(self.llbc_file_name()) - } -} diff --git a/anneal/v2/src/setup.rs b/anneal/v2/src/setup.rs deleted file mode 100644 index 9e17911f4d..0000000000 --- a/anneal/v2/src/setup.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2026 The Fuchsia Authors -// -// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 -// , or the MIT -// license , at your option. -// This file may not be copied, modified, or distributed except according to -// those terms. - -use anyhow::Context as _; - -pub struct SetupArgs { - pub local_archive: Option, -} - -exocrate::config! { - pub const CONFIG: Config = Config { - rel_dir_path: [".anneal", "toolchain"], - versioned_files: &["../Cargo.toml", "../Cargo.lock"], - }; -} - -exocrate::parse_remote_archive! { - pub const REMOTE: RemoteArchive = "Cargo.toml" [ - (linux, x86_64), - (macos, x86_64), - (linux, aarch64), - (macos, aarch64), - ]; -} - -pub enum Tool { - Cargo, - Charon, - Rustc, -} - -impl Tool { - pub fn name(&self) -> &'static str { - match self { - Self::Cargo => "cargo", - Self::Charon => "charon", - Self::Rustc => "rustc", - } - } - - pub fn path(&self, toolchain: &Toolchain) -> std::path::PathBuf { - match self { - Self::Cargo | Self::Rustc => toolchain.rust_bin().join(self.name()), - Self::Charon => toolchain.aeneas_bin_dir().join(self.name()), - } - } -} - -const AENEAS_DIR: &str = "aeneas"; -const RUST_SYSROOT: &str = "rust"; -const AENEAS_BIN_DIR: &str = "bin"; -const RUST_BIN_DIR: &str = "bin"; -const RUST_LIB_DIR: &str = "lib"; - -pub struct Toolchain { - root: std::path::PathBuf, -} - -impl Toolchain { - pub fn resolve() -> anyhow::Result { - let location = resolve_location(); - let root = CONFIG - .resolve_installation_dir(location) - .context("Toolchain not installed. Please run 'cargo anneal setup' first.")?; - Ok(Self { root }) - } - - #[cfg(all(test, feature = "exocrate_tests"))] - pub fn root(&self) -> &std::path::Path { - &self.root - } - - pub fn aeneas_bin_dir(&self) -> std::path::PathBuf { - self.root.join(AENEAS_DIR).join(AENEAS_BIN_DIR) - } - - pub fn rust_sysroot(&self) -> std::path::PathBuf { - self.root.join(RUST_SYSROOT) - } - - pub fn rust_bin(&self) -> std::path::PathBuf { - self.rust_sysroot().join(RUST_BIN_DIR) - } - - pub fn rust_lib(&self) -> std::path::PathBuf { - self.rust_sysroot().join(RUST_LIB_DIR) - } - - pub fn command(&self, tool: Tool) -> anyhow::Result { - let mut cmd = std::process::Command::new(tool.path(self)); - cmd.env_clear(); - match tool { - Tool::Cargo | Tool::Rustc => {} - Tool::Charon => { - // The archive supplies Rust tools, but not host build tools - // such as the linker. Keep the caller's `PATH` after our Rust - // bin directory so Cargo builds use the managed Rust toolchain - // while still finding those host tools. - cmd.env("CHARON_TOOLCHAIN_IS_IN_PATH", "1") - .env("PATH", prepend_current_path(self.rust_bin())?) - .env(rust_library_path_env_var(), self.rust_lib()); - } - } - Ok(cmd) - } -} - -fn prepend_current_path(path: std::path::PathBuf) -> anyhow::Result { - let mut paths = vec![path]; - if let Some(current_path) = std::env::var_os("PATH") { - paths.extend(std::env::split_paths(¤t_path)); - } - std::env::join_paths(paths).context("failed to construct PATH for tool command") -} - -/// Returns the platform library search path variable used by Rust tools. -pub(crate) fn rust_library_path_env_var() -> &'static str { - if cfg!(target_os = "macos") { "DYLD_LIBRARY_PATH" } else { "LD_LIBRARY_PATH" } -} - -pub fn run_setup(args: SetupArgs) -> anyhow::Result<()> { - let location = resolve_location(); - let source = match args.local_archive { - Some(local_archive) => exocrate::Source::Local(local_archive), - None => exocrate::Source::Remote(REMOTE), - }; - - let (installation_dir, status) = CONFIG - .resolve_installation_dir_or_install(location, source) - .context("failed to resolve-or-install dependencies")?; - match status { - exocrate::ResolvedOrInstalled::ResolvedExisting => { - log::warn!("anneal toolchain was already installed at {:?}", installation_dir); - } - exocrate::ResolvedOrInstalled::NewlyInstalled => { - log::info!("anneal toolchain freshly installed at {:?}", installation_dir); - } - } - Ok(()) -} - -fn resolve_location() -> exocrate::Location { - if std::env::var("__ANNEAL_LOCAL_DEV").is_ok() { - exocrate::Location::LocalDev - } else { - exocrate::Location::UserGlobal - } -} diff --git a/anneal/v2/src/util.rs b/anneal/v2/src/util.rs deleted file mode 100644 index 602e1585d1..0000000000 --- a/anneal/v2/src/util.rs +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2026 The Fuchsia Authors -// -// Licensed under the 2-Clause BSD License , Apache License, Version 2.0 -// , or the MIT -// license , at your option. -// This file may not be copied, modified, or distributed except according to -// those terms. - -use std::io::BufRead as _; - -use anyhow::Context as _; -use fs2::FileExt as _; - -/// Represents an active, exclusive lock on a directory. -/// -/// This struct guarantees that the process holds an OS-level file lock -/// guarding the specified directory. -pub(crate) struct DirLock { - /// The path to the directory being guarded. - pub(crate) path: std::path::PathBuf, - // Kept alive to hold the flock. - _file: std::fs::File, -} - -impl DirLock { - /// Acquires an exclusive lock on the specified directory. - /// - /// This function blocks until the lock can be acquired. We use a - /// separate `.lock` file within the directory rather than locking - /// the directory itself to avoid platform-specific issues with - /// directory locking and to ensure the lock file persists even if - /// the directory is cleaned. - pub(crate) fn lock_exclusive(path: std::path::PathBuf) -> anyhow::Result { - let file = Self::open_lock_file(&path)?; - file.lock_exclusive() - .with_context(|| format!("Failed to acquire exclusive lock on {:?}", path))?; - Ok(Self { path, _file: file }) - } - - /// Acquires a shared lock on the specified directory. - /// - /// Multiple processes can hold shared locks simultaneously, but an - /// exclusive lock will block until all shared locks are released. - #[cfg(any(test, feature = "exocrate_tests"))] - pub(crate) fn lock_shared(path: std::path::PathBuf) -> anyhow::Result { - let file = Self::open_lock_file(&path)?; - file.lock_shared() - .with_context(|| format!("Failed to acquire shared lock on {:?}", path))?; - Ok(Self { path, _file: file }) - } - - fn open_lock_file(path: &std::path::Path) -> anyhow::Result { - let lock_path = path.join(".lock"); - - // Ensure the directory exists. - if let Some(parent) = lock_path.parent() { - std::fs::create_dir_all(parent).with_context(|| { - format!("Failed to create directory for lock file: {:?}", parent) - })?; - } - // If the lock file already exists, we open it in read-only mode. - // This prevents failures if the file is read-only (e.g., after - // making the toolchain directory read-only), while still allowing - // us to acquire shared and exclusive locks on the file descriptor. - if lock_path.exists() { - std::fs::OpenOptions::new() - .read(true) - .open(&lock_path) - .with_context(|| format!("Failed to open lock file at {:?}", lock_path)) - } else { - std::fs::OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&lock_path) - .with_context(|| format!("Failed to create lock file at {:?}", lock_path)) - } - } -} - -pub(crate) struct ProcessOutput { - pub status: std::process::ExitStatus, - pub stderr_lines: Vec, -} - -/// Spawns a child process, drains its stderr in a background thread, and processes -/// its stdout line-by-line in the main thread while showing a progress spinner. -pub(crate) fn run_command_with_progress( - mut cmd: std::process::Command, - pb: Option, - mut process_stdout_line: F, -) -> anyhow::Result -where - F: FnMut(&str, Option<&indicatif::ProgressBar>) -> anyhow::Result<()>, -{ - cmd.stdout(std::process::Stdio::piped()); - cmd.stderr(std::process::Stdio::piped()); - - let mut child = cmd.spawn().context("Failed to spawn child process")?; - - let stderr_buffer = std::sync::Arc::new(std::sync::Mutex::new(Vec::new())); - let stderr_buffer_clone = std::sync::Arc::clone(&stderr_buffer); - - let mut stderr_thread = None; - if let Some(stderr) = child.stderr.take() { - stderr_thread = Some(std::thread::spawn(move || { - let reader = std::io::BufReader::new(stderr); - for line in reader.lines().map_while(Result::ok) { - stderr_buffer_clone.lock().unwrap().push(line); - } - })); - } - - if let Some(ref p) = pb { - p.enable_steady_tick(std::time::Duration::from_millis(100)); - } - - if let Some(stdout) = child.stdout.take() { - let reader = std::io::BufReader::new(stdout); - for line in reader.lines().map_while(Result::ok) { - process_stdout_line(&line, pb.as_ref())?; - if let Some(ref p) = pb { - p.tick(); - } - } - } - - if let Some(ref p) = pb { - p.finish_and_clear(); - } - - let status = child.wait().context("Failed to wait for child process")?; - - if let Some(thread) = stderr_thread { - let _ = thread.join(); - } - - let stderr_lines = std::sync::Arc::try_unwrap(stderr_buffer).unwrap().into_inner().unwrap(); - - Ok(ProcessOutput { status, stderr_lines }) -} - -/// Performs a lock test action according to the `role` of the current actor. Actors may: -/// -/// - Obtain an exclusive or shared lock for `lock_dir`, -/// - Log actions in `log_file`, -/// - Wait for a signal from `sig_file`. -/// -/// Individual tests compose multiple role-based actions and verify the resulting action log. -#[cfg(feature = "exocrate_tests")] -pub(crate) fn run_test_lock_helper( - role: &str, - lock_dir: &std::path::Path, - log_file: &std::path::Path, - sig_file: &std::path::Path, -) -> anyhow::Result<()> { - use std::io::Write as _; - - let append_log = |msg: &str| -> anyhow::Result<()> { - let mut file = std::fs::OpenOptions::new().create(true).append(true).open(log_file)?; - writeln!(file, "{}", msg)?; - Ok(()) - }; - - let wait_for_sig = || -> anyhow::Result<()> { - let start = std::time::Instant::now(); - while !sig_file.exists() { - if start.elapsed() > std::time::Duration::from_secs(3) { - anyhow::bail!("Timeout waiting for signal file {:?}", sig_file); - } - std::thread::sleep(std::time::Duration::from_millis(50)); - } - Ok(()) - }; - - match role { - "reader-a" => { - let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; - append_log("SHARED_START_A")?; - wait_for_sig()?; - append_log("SHARED_END_A")?; - } - "reader-b" => { - let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; - append_log("SHARED_START_B")?; - std::fs::write(sig_file, "")?; - append_log("SHARED_END_B")?; - } - "writer-a" => { - let _lock = DirLock::lock_exclusive(lock_dir.to_path_buf())?; - append_log("EXCLUSIVE_START_A")?; - wait_for_sig()?; - append_log("EXCLUSIVE_END_A")?; - } - "reader-exclusion" => { - std::fs::write(sig_file, "")?; - let _lock = DirLock::lock_shared(lock_dir.to_path_buf())?; - append_log("SHARED_START_B")?; - append_log("SHARED_END_B")?; - } - _ => anyhow::bail!("Unknown test-lock-helper role: {}", role), - } - - Ok(()) -} - -#[cfg(test)] -#[macro_export] -macro_rules! workspace_fixture { - ($dir:expr, { $($path:expr => $content:expr),* $(,)? }) => {{ - let root = $dir.path(); - $( - let file_path = root.join($path); - if let Some(parent) = file_path.parent() { - std::fs::create_dir_all(parent).unwrap(); - } - std::fs::write(&file_path, $content).unwrap(); - )* - }}; -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_dir_lock_exclusive_mutual_exclusion() { - let temp_dir = tempfile::tempdir().unwrap(); - let lock_path = temp_dir.path().to_path_buf(); - - let barrier = std::sync::Arc::new(std::sync::Barrier::new(2)); - let barrier_clone = std::sync::Arc::clone(&barrier); - let lock_path_clone = lock_path.clone(); - - let lock_released = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let lock_released_clone = std::sync::Arc::clone(&lock_released); - - // Thread A acquires the lock. - let thread_a = std::thread::spawn(move || { - let _lock = DirLock::lock_exclusive(lock_path_clone).expect("Failed to lock exclusive"); - barrier_clone.wait(); // Signal Thread B that A holds the lock. - - // Simulate brief work holding the lock. - std::thread::sleep(std::time::Duration::from_millis(100)); - lock_released_clone.store(true, std::sync::atomic::Ordering::Relaxed); - // _lock drops here, releasing the lock. - }); - - // Thread B waits for Thread A to acquire the lock, then tries to acquire it itself. - let thread_b = std::thread::spawn(move || { - barrier.wait(); // Wait for Thread A to acquire lock. - - // Attempt to acquire lock. This should block until Thread A releases it. - let _lock = DirLock::lock_exclusive(lock_path).expect("Failed to lock exclusive in B"); - - // Assert that B only successfully locked the directory AFTER A released it. - assert!( - lock_released.load(std::sync::atomic::Ordering::Relaxed), - "Thread B acquired lock before Thread A released it!" - ); - }); - - thread_a.join().unwrap(); - thread_b.join().unwrap(); - } - - #[test] - fn test_dir_lock_shared_coexistence() { - let temp_dir = tempfile::tempdir().unwrap(); - let lock_path = temp_dir.path().to_path_buf(); - - // Thread A acquires shared lock. - let lock_a = DirLock::lock_shared(lock_path.clone()).expect("Failed to lock shared"); - - // Thread B should be able to acquire shared lock immediately without blocking. - let lock_b = DirLock::lock_shared(lock_path).expect("Failed to lock shared concurrently"); - - // Both locks are held. - drop(lock_a); - drop(lock_b); - } -} diff --git a/ci/check_fmt.sh b/ci/check_fmt.sh index 1e17b4e468..c9ea6b63d2 100755 --- a/ci/check_fmt.sh +++ b/ci/check_fmt.sh @@ -23,5 +23,5 @@ zerocopy/ci/check_fmt.sh "$@" cargo +"$NIGHTLY" fmt --manifest-path tools/Cargo.toml --all "${FMT_FLAGS[@]}" >&2 cargo +"$NIGHTLY" fmt --manifest-path anneal/Cargo.toml --all "${FMT_FLAGS[@]}" >&2 -cargo +"$NIGHTLY" fmt --manifest-path anneal/v2/Cargo.toml --all "${FMT_FLAGS[@]}" >&2 +cargo +"$NIGHTLY" fmt --manifest-path anneal/v1/Cargo.toml --all "${FMT_FLAGS[@]}" >&2 cargo +"$NIGHTLY" fmt --manifest-path exocrate/Cargo.toml "${FMT_FLAGS[@]}" >&2 diff --git a/ci/release_anneal_version.sh b/ci/release_anneal_version.sh index f28d0ef285..d66cce51fd 100755 --- a/ci/release_anneal_version.sh +++ b/ci/release_anneal_version.sh @@ -20,16 +20,16 @@ VERSION="$1" # Update the package version in the Anneal crate's manifest. This is the # authoritative version for the crate. -sed -i -e "s/^version = \"[0-9a-zA-Z\.-]*\"/version = \"$VERSION\"/" anneal/Cargo.toml +sed -i -e "s/^version = \"[0-9a-zA-Z\.-]*\"/version = \"$VERSION\"/" anneal/v1/Cargo.toml # Update the installation instructions in the README to reflect the new version. # This ensures that users copying instructions get the latest version. -sed -i -e "s/cargo install cargo-anneal@[0-9a-zA-Z\.-]*/cargo install cargo-anneal@$VERSION/" anneal/README.md +sed -i -e "s/cargo install cargo-anneal@[0-9a-zA-Z\.-]*/cargo install cargo-anneal@$VERSION/" anneal/v1/README.md # Update Cargo.lock to reflect the version change in Cargo.toml. We must run -# this in the anneal subdirectory because it is a separate workspace with its +# this in the anneal/v1 subdirectory because it is a separate workspace with its # own lockfile. Use `cargo update` on the local package itself instead of # regenerating the entire lockfile; the release version bump should not also # roll dependency versions. -cd anneal +cd anneal/v1 cargo update -p cargo-anneal --precise "$VERSION" diff --git a/hermes b/hermes index 103b3362a1..76e9261845 120000 --- a/hermes +++ b/hermes @@ -1 +1 @@ -anneal/ \ No newline at end of file +anneal/v1/ \ No newline at end of file diff --git a/tools/hermes b/tools/hermes index e567b44430..9833c976ef 120000 --- a/tools/hermes +++ b/tools/hermes @@ -1 +1 @@ -../anneal/ \ No newline at end of file +../anneal/v1/ \ No newline at end of file From 6baa62bcbea34c827a882d3685f0e14bb8879094 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Fri, 17 Jul 2026 15:23:06 +0000 Subject: [PATCH 2/2] [anneal] Add more thorough agent documentation gherrit-pr-id: Gbzsorhgbclv3optfx2dkxjelijhcdfds --- anneal/AGENTS.md | 95 +++++ anneal/README.md | 169 ++++++++ anneal/agent_docs/README.md | 137 +++++++ anneal/agent_docs/agent-corpus.md | 93 +++++ .../design/decisions/0000-template.md | 57 +++ .../0001-v2-is-a-clean-room-redesign.md | 82 ++++ .../0002-verification-is-artifact-scoped.md | 94 +++++ .../0003-expanded-generated-rust-is-input.md | 96 +++++ ...4-invariants-support-all-property-kinds.md | 94 +++++ ...-adoption-supports-prose-justifications.md | 99 +++++ ...0006-the-tcb-is-explicit-and-shrinkable.md | 122 ++++++ anneal/agent_docs/design/decisions/README.md | 60 +++ .../design/open-questions/README.md | 76 ++++ .../aeneas-charon-integration.md | 151 +++++++ .../contracts-and-invariants.md | 176 +++++++++ .../memory-resources-and-effects.md | 159 ++++++++ .../proof-authoring-and-user-experience.md | 177 +++++++++ .../property-kinds-and-outcomes.md | 164 ++++++++ .../open-questions/rust-safety-integration.md | 165 ++++++++ .../open-questions/source-model-adequacy.md | 168 ++++++++ .../trust-and-incremental-adoption.md | 163 ++++++++ anneal/agent_docs/design/principles.md | 144 +++++++ anneal/agent_docs/design/result-and-trust.md | 374 ++++++++++++++++++ .../agent_docs/design/settled-requirements.md | 274 +++++++++++++ .../agent_docs/design/verification-model.md | 239 +++++++++++ anneal/agent_docs/design/worked-example.md | 226 +++++++++++ anneal/agent_docs/glossary.md | 247 ++++++++++++ anneal/agent_docs/history/research-index.md | 184 +++++++++ anneal/agent_docs/history/v1-lessons.md | 196 +++++++++ .../agent_docs/reference/aeneas-and-charon.md | 83 ++++ .../reference/current-priorities.md | 108 +++++ anneal/agent_docs/reference/current-state.md | 157 ++++++++ .../reference/development-and-ci.md | 146 +++++++ anneal/v1/AGENTS.md | 14 +- anneal/v1/README.md | 7 + 35 files changed, 4992 insertions(+), 4 deletions(-) create mode 100644 anneal/AGENTS.md create mode 100644 anneal/README.md create mode 100644 anneal/agent_docs/README.md create mode 100644 anneal/agent_docs/agent-corpus.md create mode 100644 anneal/agent_docs/design/decisions/0000-template.md create mode 100644 anneal/agent_docs/design/decisions/0001-v2-is-a-clean-room-redesign.md create mode 100644 anneal/agent_docs/design/decisions/0002-verification-is-artifact-scoped.md create mode 100644 anneal/agent_docs/design/decisions/0003-expanded-generated-rust-is-input.md create mode 100644 anneal/agent_docs/design/decisions/0004-invariants-support-all-property-kinds.md create mode 100644 anneal/agent_docs/design/decisions/0005-incremental-adoption-supports-prose-justifications.md create mode 100644 anneal/agent_docs/design/decisions/0006-the-tcb-is-explicit-and-shrinkable.md create mode 100644 anneal/agent_docs/design/decisions/README.md create mode 100644 anneal/agent_docs/design/open-questions/README.md create mode 100644 anneal/agent_docs/design/open-questions/aeneas-charon-integration.md create mode 100644 anneal/agent_docs/design/open-questions/contracts-and-invariants.md create mode 100644 anneal/agent_docs/design/open-questions/memory-resources-and-effects.md create mode 100644 anneal/agent_docs/design/open-questions/proof-authoring-and-user-experience.md create mode 100644 anneal/agent_docs/design/open-questions/property-kinds-and-outcomes.md create mode 100644 anneal/agent_docs/design/open-questions/rust-safety-integration.md create mode 100644 anneal/agent_docs/design/open-questions/source-model-adequacy.md create mode 100644 anneal/agent_docs/design/open-questions/trust-and-incremental-adoption.md create mode 100644 anneal/agent_docs/design/principles.md create mode 100644 anneal/agent_docs/design/result-and-trust.md create mode 100644 anneal/agent_docs/design/settled-requirements.md create mode 100644 anneal/agent_docs/design/verification-model.md create mode 100644 anneal/agent_docs/design/worked-example.md create mode 100644 anneal/agent_docs/glossary.md create mode 100644 anneal/agent_docs/history/research-index.md create mode 100644 anneal/agent_docs/history/v1-lessons.md create mode 100644 anneal/agent_docs/reference/aeneas-and-charon.md create mode 100644 anneal/agent_docs/reference/current-priorities.md create mode 100644 anneal/agent_docs/reference/current-state.md create mode 100644 anneal/agent_docs/reference/development-and-ci.md diff --git a/anneal/AGENTS.md b/anneal/AGENTS.md new file mode 100644 index 0000000000..8f11cd91d3 --- /dev/null +++ b/anneal/AGENTS.md @@ -0,0 +1,95 @@ + + +# Anneal agent guide + +This file governs work in `anneal/`. Work under `anneal/v1/` must also follow +the more specific `v1/AGENTS.md`. + +Anneal is a clean-room, ground-up redesign of the experimental V1 prototype. +V1 is useful evidence, not a default architecture, specification language, or +user interface. Reuse a V1 idea or implementation only after evaluating it +against the current design. + +## Mission + +Anneal is a general verification tool for Rust, with unsafe-code soundness as +its foundational use case. It aims to let ordinary Rust teams verify subtle +properties of real Rust programs while preserving the guarantees expected of +safe Rust. + +Soundness is non-negotiable. Rust compilers and Anneal's source models need not +preserve a program's behavior after undefined behavior, so Anneal must establish +the soundness conditions on which its own model fidelity depends. Never gain +simplicity, coverage, or convenience by weakening such a condition, silently +omitting an operation, or hiding trust. + +## Start here + +`agent_docs/` is the canonical project context and design corpus written for +coding agents. It is not Anneal's user-facing documentation surface. Human +maintainers may read and edit it, but its organization and wording should be +optimized for agent ingestion and judgment. + +In an unfamiliar checkout, first complete the +[agent-corpus preflight](agent_docs/agent-corpus.md). Then follow the canonical +[documentation map](agent_docs/README.md), which owns the reading order, +document authority, and reconciliation procedure for the design canon. + +## Working protocol + +- Evaluate alternatives using the + [design principles](agent_docs/design/principles.md) and satisfy every + applicable + [settled requirement](agent_docs/design/settled-requirements.md). +- Follow accepted decision records. Treat open-question documents, issues, + pull requests, research, experiments, and V1 as evidence rather than settled + authority. +- Do not settle an open design incidentally in implementation. Before a change + commits the project to an answer, obtain explicit agreement from the project + authors and record the accepted decision. Otherwise label the implementation + as an experiment or surface the choice. +- If documents disagree, surface and reconcile the disagreement using the + process in the documentation map instead of silently choosing convenient + text. +- Fail closed relative to the exact claim being reported. Unsupported + semantics, omitted coverage, hidden assumptions, and undischarged obligations + must not produce an unconditional verification claim. +- Determine current behavior from the checked-in code and the + [current-state reference](agent_docs/reference/current-state.md). Open or + stacked pull requests may provide context, but are not authoritative for the + current checkout. +- Prefer existing, maintained Lean, Aeneas, Charon, and Rust mechanisms when + they fit. Flag abstractions or extensions which may belong upstream; decide + ownership case by case, including the maintenance burden on collaborators. +- Prefer robust programmatic interfaces over textual patching and keep the + proof and diagnostic experience usable by ordinary Rust engineers. + +### Applying the design principles + +When settled requirements and accepted decisions do not determine an answer: + +1. state the exact claim each alternative would support; +2. identify added trust, lost coverage, or omitted semantic information; +3. ask whether the result still composes at an established abstraction + boundary; +4. consider usability, maintenance, and the path to broader coverage; +5. prefer reversible experiments while evidence is weak. + +## Documentation maintenance + +- Update the design canon in the same change that alters a settled contract, + trust boundary, or project-wide constraint. +- Give requirements stable identifiers and link implementation decisions back + to them. +- Record meaningful evidence and rejected alternatives, but remove temporary + misunderstandings once terminology has been clarified. +- Keep current-state references synchronized with checked-in behavior. Issues + and pull requests are guides to thinking, not specifications. +- Link to each explanation's canonical owner instead of duplicating it across + agent instructions or corpus pages. diff --git a/anneal/README.md b/anneal/README.md new file mode 100644 index 0000000000..f9df49bc9b --- /dev/null +++ b/anneal/README.md @@ -0,0 +1,169 @@ + + +# Anneal + +Anneal is a verification tool for Rust. It helps developers replace informal +reasoning about unsafe code with checked proofs, and it can also verify precise +application-specific promises about program behavior. + +> **Status:** Anneal is under active construction and cannot yet verify +> applications. The checked-in executable currently provides only toolchain +> setup infrastructure. The example below illustrates the problem Anneal +> addresses, not a workflow which is currently available. + +## Why Anneal exists + +Rust's safe APIs promise that ordinary, type-checked use will not cause +undefined behavior—for example, an invalid memory access or a data race. We +call this guarantee soundness: every use which the safe API permits must remain +free from undefined behavior. Safe code can still panic, run forever, or +produce the wrong answer, but a safe API must remain sound even when it uses +unsafe code internally. + +Unsafe Rust lets a programmer perform operations whose soundness the compiler +cannot verify. Each such operation comes with requirements: a pointer might +need to refer to live memory, an index might need to be in bounds, or a value +might need to be initialized. The compiler accepts the operation because the +programmer takes responsibility for meeting those requirements. + +That reasoning is usually recorded in a comment: + +```rust +pub fn get_byte(bytes: &[u8], index: usize) -> u8 { + assert!(index < bytes.len()); + + // SAFETY: `bytes` is a valid slice and `index` is in bounds, so this + // pointer may be dereferenced. + unsafe { *bytes.as_ptr().add(index) } +} +``` + +A reviewer can understand this argument, but Rust does not check that the +comment is correct or remains correct after a refactor. If the bounds check is +removed or moved too late, the unsafe operation's requirements may no longer +hold while the comment continues to look reassuring. + +Because `get_byte` is a safe function, callers may pass any `usize`. An +out-of-bounds call may panic at the assertion, but it must never cause undefined +behavior. A safe API must not place a hidden safety requirement on its caller. + +Anneal turns reasoning like the safety comment into proof obligations checked +by [Lean](https://lean-lang.org/), a language which mechanically checks +mathematical arguments. If Anneal cannot establish an obligation, it reports +the gap and identifies the operation which produced it instead of silently +treating the comment as proof. An undischarged obligation is a verification +failure and a useful diagnostic; by itself, it does not prove that the Rust +code is unsound. + +This is intentionally a tiny example; ordinary Rust should simply use +`bytes[index]`. It stands in for implementations which cannot avoid unsafe +operations. It contains no Anneal-specific syntax because the specification +and proof-authoring interface is still being designed. + +## What Anneal adds + +Anneal lets a project describe: + +- the requirements a caller must satisfy before using an unsafe API; +- the promises a function or type makes to its callers; and +- the reasoning which connects ordinary Rust code to those requirements and + promises. + +Anneal checks the Rust safety obligations within the claimed scope, including +the requirements of unsafe operations and the promises on which safe APIs +rely. It follows those promises through function calls, so a verified +implementation can be used through its API without every caller re-examining +its private unsafe code. + +For a safe abstraction, the goal is straightforward: callers can use the safe +API according to the normal Rust type system, with no hidden rule whose +violation could cause undefined behavior. An unsafe API may explicitly give +part of that responsibility to its caller—for example, through a function +declared `unsafe` with documented requirements. + +## What a verification result means + +**Note:** The exact report format and command behavior are still being designed. + +A successful Anneal result identifies the particular code and build it covers +and states which guarantees were checked. At a minimum, it establishes that: + +- every safety-relevant operation within the named coverage satisfies Rust's + requirements; +- the functions and types checked by Anneal keep the promises stated in their + specifications; and +- anything Anneal could not prove, deliberately trusted, or did not cover is + listed rather than silently included in an unconditional claim. + +For example, a result might cover one Cargo target with a particular feature +set and dependency graph. It should say whether generated Rust, dependencies, +and calls into foreign code were checked, trusted, or outside its coverage. + +When Anneal reports that a safe abstraction itself has been verified within a +stated semantic and build envelope, every type-correct safe use which the API +permits within that envelope should be safe—not only the calls which happened +to appear in one test or binary. Any assumptions on that claim must be listed +explicitly. + +Verification does not mean that the program has no bugs. It applies only to +the guarantees and build configuration named in the result. Changing the +target, feature set, dependency, compiler configuration, or generated source +may require checking the program again. + +For promises beyond Rust safety, Anneal checks whether the code satisfies the +specification it was given; it cannot decide whether that specification says +what its author truly wanted. A weak or mistaken specification can describe +the wrong behavior. It cannot, however, erase the Rust safety requirements +which Anneal is responsible for checking. + +## Beyond Rust safety + +Rust safety is only one part of program correctness. A memory-safe function can +still return the wrong answer or panic unexpectedly. Anneal also aims to check +additional promises, for example: + +- a parser returns the value described by its input; +- an operation does not panic when its documented requirements hold; +- a data structure preserves the rules expected by its public API; or +- an implementation follows an application or network protocol. + +Each promise must be stated precisely enough to prove. Anneal should make +common cases approachable while leaving Lean available for specifications and +proofs which need its full expressive power. + +## Incremental adoption + +Adopting formal verification across an existing codebase takes time. Anneal +lets teams begin with their highest-risk code and expand coverage gradually. + +During that process, some unsafe operations may still rely on prose +`// SAFETY:` comments, unfinished proofs, or trusted external behavior. Anneal +reports those portions honestly rather than treating them as machine-checked +facts. This lets a team see what has been proved and what work or trust remains. + +## Under the hood: Lean + +Lean checks Anneal's mathematical arguments. Some specifications or advanced +proofs may be written directly in Lean, while Anneal connects them to the Rust +program and presents useful obligations and diagnostics to Rust developers. + +Lean can check only the statement it receives. A meaningful result therefore +also depends on Anneal connecting that statement to the right Rust program and +reporting any external assumptions. Users should not need to understand the +translation machinery, but they must be able to see the assumptions and gaps +which qualify a result. + +## Repository development + +Coding agents working on Anneal must begin with [`AGENTS.md`](AGENTS.md). It +routes them into `agent_docs/`, an internal corpus written for agent +consumption. That corpus contains design context, current implementation facts, +and operating guidance which are intentionally omitted from this user-facing +introduction. Human maintainers may consult it, but it is not part of Anneal's +user documentation or a stable product interface. diff --git a/anneal/agent_docs/README.md b/anneal/agent_docs/README.md new file mode 100644 index 0000000000..2adce26398 --- /dev/null +++ b/anneal/agent_docs/README.md @@ -0,0 +1,137 @@ + + +# Anneal agent documentation + +This directory is the canonical project context and design corpus written for +coding agents working on the current Anneal redesign. It is not user-facing +documentation or a stable product interface. Human maintainers may inspect, +review, and edit it, but its structure and explanations should optimize agent +comprehension, judgment, and reliable action. + +Agent-oriented organization does not mean prompt-fragment prose. Design pages +should explain rationale declaratively in language human maintainers can audit; +imperative agent procedure belongs in `AGENTS.md` or an explicitly labeled +instruction section. + +This page is the canonical owner of the agent reading order, document +authority, and reconciliation process. Other agent instructions may point here, +but must not maintain a competing copy of that information. + +## Reading order + +Agents should first follow [`AGENTS.md`](../AGENTS.md). In an unfamiliar +checkout, complete the [agent-corpus preflight](agent-corpus.md) before relying +on any local document. + +Before making or reviewing a design change, read the following completely, in +order: + +1. The user-facing [project introduction](../README.md), to understand the + audience and product promise. +2. [Glossary](glossary.md), for stable vocabulary used throughout the canon. +3. [Principles](design/principles.md), for the goals and choice rules behind + design judgment. +4. [Settled requirements](design/settled-requirements.md), for constraints + every acceptable design must meet. +5. [Accepted decisions](design/decisions/README.md), including every decision + relevant to the change. +6. [Verification model](design/verification-model.md), for the intended local + proof and global composition argument. +7. [Result and trust model](design/result-and-trust.md), for the identity and + scope of a claim, its evidence, its residual dependencies, and what must be + reported. +8. [Worked example](design/worked-example.md), as an illustration whose + concrete proof choices are not decisions unless the text cites one. +9. [Open questions](design/open-questions/README.md), including every page + relevant to the task. Candidate approaches are not decisions. +10. [Current state](reference/current-state.md) and the explicitly + non-normative [current priorities](reference/current-priorities.md), for + checked-in behavior and the present engineering frontier. + +For translation, semantics, or proof-infrastructure work, also read +[Aeneas and Charon](reference/aeneas-and-charon.md). Read +[development and CI](reference/development-and-ci.md) before changing commands +or automation. Read [V1 lessons](history/v1-lessons.md) before borrowing from +the prototype, and inspect V1 itself only when the task requires primary +historical evidence. + +The [agent-corpus guide](agent-corpus.md) explains how to discover every +documentation file for a full audit or context-free comprehension test. + +## Document classes + +### Navigation and vocabulary + +This map, the [agent-corpus guide](agent-corpus.md), and the +[glossary](glossary.md) help readers find and interpret the canon. They do not +create design commitments independently of the normative documents and +accepted decisions they describe. + +### Normative design + +The files directly under [`design/`](design/) give the current consolidated +design. Principles guide choices; settled requirements constrain every +acceptable design. The worked example is a teaching companion: its concrete +choices are illustrative, and only the requirements and decisions it cites are +normative. + +### Accepted decisions + +Records under [`design/decisions/`](design/decisions/README.md) capture an +accepted choice, its rationale, and its consequences. A decision changes only +through an explicit amendment or superseding record. Consolidated design files +must be updated when such a change affects their account. + +### Open questions + +Files under [`design/open-questions/`](design/open-questions/README.md) are +design workspaces. Their settled constraints come from the normative documents +and accepted decisions they cite. Candidate approaches, provisional analyses, +and implementation experiments do not settle the question. + +### Reference + +Files under [`reference/`](reference/current-state.md) describe checked-in +code, commands, external tools, and current limitations. They are factual, not +aspirational. The dated +[current-priorities page](reference/current-priorities.md) is non-normative +guidance for the present engineering frontier. References must label intended +future roles and defer to the normative design where appropriate. + +### History and research + +Files under [`history/`](history/v1-lessons.md) preserve evidence, lessons, and +source indexes. V1, issues, pull requests, and research papers may motivate a +decision but do not override the current canon. Volatile source indexes must be +dated. + +## Resolving disagreements + +If normative files disagree with one another, or a consolidated design file +disagrees with an accepted decision, do not silently select one. Check whether +one record explicitly supersedes the other, then surface and repair the +inconsistency. Until it is reconciled, avoid making an irreversible design +choice which depends on the disputed point. + +Do not promote language from an open question, issue, pull request, experiment, +or V1 into a settled claim merely because it is convenient or has been +implemented. Record the decision first or continue to label the implementation +as an experiment. + +## Changing the canon + +A project-wide question becomes settled only with explicit agreement from the +project authors; implementation alone is not ratification. After agreement: + +1. add or update an accepted decision record; +2. update the relevant normative design files; +3. update the status and links of affected open questions; +4. update current-state references if checked-in behavior changed; and +5. preserve significant evidence and genuinely considered alternatives without + retaining obsolete conversational misunderstandings. diff --git a/anneal/agent_docs/agent-corpus.md b/anneal/agent_docs/agent-corpus.md new file mode 100644 index 0000000000..fbe5ebd73f --- /dev/null +++ b/anneal/agent_docs/agent-corpus.md @@ -0,0 +1,93 @@ + + +# Anneal agent corpus + +This page helps a context-free agent find and ingest the current Anneal agent +documentation without confusing a worktree container, another checkout, or +the historical V1 prototype for the intended corpus. The +[documentation map](README.md) is the sole owner of reading order and document +authority. + +## Establish the Anneal root + +Resolve the repository root from the current checkout; never copy an absolute +path from another session. The corpus root is its `anneal/` directory, which +must contain the crate and the documentation entrypoints: + +```bash +repo_root="$(git rev-parse --show-toplevel)" +anneal_root="$repo_root/anneal" + +test -f "$anneal_root/Cargo.toml" +test -f "$anneal_root/AGENTS.md" +test -f "$anneal_root/README.md" +test -f "$anneal_root/agent_docs/README.md" +test -f "$anneal_root/agent_docs/agent-corpus.md" +``` + +These structural checks deliberately avoid exact headings, hashes, and byte +counts. Routine documentation edits should not break discovery. If a marker is +missing, stop and locate the correct worktree instead of substituting a +similarly named directory. + +## Exclude V1 + +`anneal/v1/` is the historical prototype and is **not part of the current +corpus**. Do not recursively ingest it, follow its `AGENTS.md` as current +instructions, or use its README to replace a missing current file. Read +selected V1 documentation or source only when current documentation calls for +historical evidence, and treat it as history rather than authority. The +[V1 lessons](history/v1-lessons.md) page is the normal starting point. + +An `AGENTS.md` above `anneal/` may still impose repository or worktree +procedures. Those instructions apply to repository operations, but do not +replace Anneal's project and design canon. + +## Discover the complete corpus + +For a full documentation audit or a context-free comprehension test, read: + +- `anneal/AGENTS.md`; +- `anneal/README.md`; and +- every Markdown file under `anneal/agent_docs/`, recursively. + +Discover the last category from the filesystem instead of maintaining another +hand-written enumeration: + +```bash +find "$anneal_root/agent_docs" -type f -name '*.md' \ + ! -path '*/design/decisions/0000-template.md' -print | sort +``` + +Follow the order in the [documentation map](README.md). Do not add +`anneal/v1/**/*.md` to the corpus. Source code, issues, pull requests, and +upstream documentation may be necessary evidence for a task, but reading them +alongside the corpus does not give them design authority. + +`design/decisions/0000-template.md` is authoring scaffolding rather than a +decision, so it is deliberately excluded from a comprehension corpus. + +## Completion check + +After reading, a context-free agent should be able to explain, without relying +on V1 or an open pull request: + +- Anneal's product goal, intended users, and why soundness is foundational; +- the principles used to compare designs and the constraints every acceptable + design must satisfy; +- which documents are normative, accepted, open, factual, or historical; +- how an identified Rust subject, a precise claim, checked evidence, and + classified residual dependencies form a reported result; +- how local proofs compose into a global claim and why the source model must be + adequate for that argument; +- what the checked-in executable actually implements today; and +- which unresolved choice the current task must not settle silently. + +If the corpus does not support one of those answers, report the gap rather than +importing an answer from V1, an issue, or a pull request. diff --git a/anneal/agent_docs/design/decisions/0000-template.md b/anneal/agent_docs/design/decisions/0000-template.md new file mode 100644 index 0000000000..655302d089 --- /dev/null +++ b/anneal/agent_docs/design/decisions/0000-template.md @@ -0,0 +1,57 @@ + + +# NNNN: Short decision title + +- **Status:** Proposed +- **Date:** YYYY-MM-DD + +## Context + +Describe the problem, the constraints already settled elsewhere, and why a +decision is needed. Separate observations from assumptions. + +## Decision + +State the decision precisely enough that an implementer can tell whether a +proposal complies with it. Prefer a narrow commitment over settling adjacent +questions without evidence. + +## Rationale + +Explain how this decision follows from Anneal's [principles](../principles.md) +and why the tradeoff is appropriate. + +## Consequences + +List the useful constraints and the costs this decision introduces. Include +effects on soundness, user-visible claims, maintainability, and migration when +they are relevant. + +## Alternatives considered + +Describe credible alternatives and why they were not chosen. Not choosing an +alternative now need not mean rejecting it forever. + +## Deferred questions + +List choices this record intentionally does not make. Link them to the relevant +[open-question document](../open-questions/README.md) where possible. + +## Evidence + +Link primary sources, experiments, V1 lessons, or explicit design conclusions +which support the decision. Mark historical or potentially stale sources as +such. + +## Links + +- [Design principles](../principles.md) +- [Settled requirements](../settled-requirements.md) +- Related decisions and open questions + diff --git a/anneal/agent_docs/design/decisions/0001-v2-is-a-clean-room-redesign.md b/anneal/agent_docs/design/decisions/0001-v2-is-a-clean-room-redesign.md new file mode 100644 index 0000000000..645a94dc10 --- /dev/null +++ b/anneal/agent_docs/design/decisions/0001-v2-is-a-clean-room-redesign.md @@ -0,0 +1,82 @@ + + +# 0001: V2 is a clean-room redesign + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +Anneal V1 was an early experiment and demonstration. It established that parts +of the idea were useful, but it also embedded provisional choices about syntax, +proof structure, trust, and integration with Aeneas. Treating those choices as +an inherited compatibility surface would turn experiments into constraints +before V2's requirements are understood. + +V1 remains valuable evidence. Some of its code and designs may still be the +best way to implement a V2 requirement. + +## Decision + +Anneal V2 is a clean-room, ground-up rewrite and redesign. The presence of a +concept, interface, or implementation in V1 creates no presumption that V2 will +retain it. + +V2 may borrow or copy from V1 when a fresh evaluation shows that doing so serves +V2's principles and requirements. V2 documentation may refer to V1 to record a +lesson, or after a V1 choice has independently been accepted for V2. In all +other cases, V1 is historical context rather than design authority. + +Here, “clean-room” describes design inheritance; it is not a prohibition on +reusing suitable code. + +## Rationale + +Anneal's purpose requires substantial changes to the prototype. Starting from +the desired assurance and user experience keeps accidental V1 constraints from +outweighing soundness, semantic fidelity, composability, or maintainability. +Retaining V1 as evidence still lets V2 benefit from working code and hard-won +lessons. + +## Consequences + +- V2 proposals must be justified from current requirements and principles, not + merely by matching V1. +- Compatibility with V1 syntax, generated Lean, or workflows is not a default + requirement. +- Copying a V1 component requires checking that its assumptions still hold. +- V1 documentation lives under [`v1/`](../../../v1/) and must not be read as V2 + documentation. +- Lessons from V1 should be distilled into V2 history documents instead of + requiring contributors to reverse-engineer the prototype. + +## Deferred questions + +- Which V1 components, if any, should be reused? +- Will V2 offer migration tools or compatibility syntax for V1 users? +- What specification language, proof surface, and generated-Lean interface + should V2 expose? + +Those questions belong in the relevant +[open design discussions](../open-questions/README.md), not in this record. + +## Evidence + +- The project author explicitly characterized V1 as an early experimental and + demonstration prototype and V2 as a clean-room redesign. +- The [V1 design document](../../../v1/docs/design/design.md) records several + prototype-specific choices which are being reconsidered. +- [V1 lessons](../../history/v1-lessons.md) distills the evidence that should + inform V2 without becoming implicit precedent. + +## Links + +- [Design principles](../principles.md) +- [Settled requirements](../settled-requirements.md) +- [V1 lessons](../../history/v1-lessons.md) diff --git a/anneal/agent_docs/design/decisions/0002-verification-is-artifact-scoped.md b/anneal/agent_docs/design/decisions/0002-verification-is-artifact-scoped.md new file mode 100644 index 0000000000..1c8b02ffff --- /dev/null +++ b/anneal/agent_docs/design/decisions/0002-verification-is-artifact-scoped.md @@ -0,0 +1,94 @@ + + +# 0002: Verification is artifact-scoped + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +The meaning of Rust source depends on its compilation. Target, enabled features, +`cfg` values, panic strategy, dependency resolution, compiler behavior, and +environmental inputs can all change the program which is compiled. A claim +phrased only as “this library is verified” would therefore leave its subject +ambiguous. + +Anneal may eventually help users verify a matrix of configurations, but a +matrix is a collection of claims and not the initial atomic claim. + +## Decision + +The initial unit of an Anneal source-level verification claim is one Cargo +compilation artifact under a fixed target, configuration, feature set, panic +strategy, dependency graph, and relevant environment. + +A successful verification of one artifact does not imply that another target +or configuration has been verified. A command may eventually orchestrate +several artifacts, but each artifact remains a separately identified claim. + +## Rationale + +Scoping the claim to the program the compiler actually constructs makes it +precise and auditable. It avoids universal claims over code configurations that +Anneal has not analyzed while leaving room for higher-level matrix tooling. + +## Consequences + +- Verification output must identify its compilation subject sufficiently for a + user or auditor to distinguish it from other builds. +- Changing a claim-relevant compilation input produces a different artifact and + requires a new verification claim. +- Cross-target or all-features assurance requires verifying every intended + artifact or separately proving why the claim generalizes. +- Caches must not reuse a result across claim-relevant inputs without a sound + equivalence argument. +- The exact compilation-subject identity, verification-result identity, and + audit-ledger schema remain design work. + +## Alternatives considered + +### Claim verification for the source tree + +A source tree admits many semantically different builds, so this would obscure +which program was analyzed. + +### Require an entire configuration matrix as the atomic unit + +This would make early adoption unnecessarily expensive and still require a +definition of which matrix is complete. + +### Scope only to a crate and target triple + +Features, `cfg`, dependencies, panic behavior, and environmental inputs can +change semantics even when those two values are unchanged. + +## Deferred questions + +- Which inputs must be recorded, normalized, or content-addressed? +- Which host tools, environment variables, compiler flags, and target + specifications can change the compilation subject, and which instead belong + only to verification-result identity or the trust ledger? +- Should `cargo anneal verify` support build matrices, and how should it report + aggregate results? +- How do compilation-subject and verification-result identities appear in the + TCB audit ledger? + +## Evidence + +- The project author selected one fixed Cargo compilation artifact, rather than + a matrix of builds, as the exact initial unit of a source-level claim. +- Rust's compilation model makes target, `cfg`, features, panic strategy, + dependencies, and generated inputs semantically relevant. + +## Links + +- [Generated Rust is input](0003-expanded-generated-rust-is-input.md) +- [The TCB is explicit and shrinkable](0006-the-tcb-is-explicit-and-shrinkable.md) +- [Trust and incremental adoption](../open-questions/trust-and-incremental-adoption.md) +- [Design principles](../principles.md) diff --git a/anneal/agent_docs/design/decisions/0003-expanded-generated-rust-is-input.md b/anneal/agent_docs/design/decisions/0003-expanded-generated-rust-is-input.md new file mode 100644 index 0000000000..c8beccc0ed --- /dev/null +++ b/anneal/agent_docs/design/decisions/0003-expanded-generated-rust-is-input.md @@ -0,0 +1,96 @@ + + +# 0003: Expanded, generated Rust is verification input + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +Procedural macros and build scripts can generate Rust which becomes part of the +compiled program. Trusting a generator in place of analyzing its output would +exclude real program behavior from Anneal's claim. Requiring generated Rust to +be checked in would also misrepresent normal Cargo builds. + +This decision concerns generated Rust that enters the program seen by Charon. +It does not by itself settle how to treat every side effect of a build script, +foreign libraries selected for linking, or generator execution as a separate +program. + +## Decision + +Rust generated by procedural macros or build scripts and subsequently ingested +by Charon is verification input, just like checked-in Rust source. Its origin +does not exempt it from the obligations that apply to the rest of the compiled +artifact. + +The generator is not trusted as a substitute for checking the generated Rust. +Anneal analyzes the expanded program which participates in the artifact's +semantics. + +## Rationale + +Anneal's claim must track the code which is compiled, not only the files a human +checked into version control. Treating expanded code uniformly improves +semantic fidelity and lets ordinary Rust projects use their existing code +generation practices without adding generated source to the repository. + +## Consequences + +- Anneal must obtain an authoritative representation of generated Rust from the + compiler pipeline. +- Generated code can introduce proof obligations and trusted leaves just as + handwritten code can. +- Diagnostics should retain useful provenance back to a macro invocation or + generator where the toolchain makes that possible. +- The compilation-subject identity must account for inputs that can change + generated code. +- This record does not choose LLBC-only ingestion, a compiler metadata service, + or a source-level annotation scanner. + +## Alternatives considered + +### Trust procedural macros and build scripts + +That would place arbitrary generated program behavior outside the checked +artifact and unnecessarily enlarge the TCB. + +### Analyze only checked-in source + +The analyzed program could then differ from the program rustc compiles. + +### Require generated Rust to be checked in + +This does not match common Rust workflows and would not prove that the checked- +in output is the output used for the verified compilation. + +## Deferred questions + +- Which Charon or rustc interface should expose expanded code, annotations, item + identities, and call metadata? +- How should diagnostics map generated definitions to their source origins? +- Which build-script effects change the compilation subject, and which belong + only to verification-result identity or the trust ledger? +- How should generated native code, linked libraries, and other non-Rust output + be modeled? +- Must generator execution itself be reproducible or verified? + +## Evidence + +- The project author explicitly classified proc-macro- and build-script- + generated Rust as input which Charon ingests, rather than trusted source. +- Charon's compiler-derived program representation already includes code after + Rust compilation has resolved forms that a source-only scanner cannot fully + recover. + +## Links + +- [Verification is artifact-scoped](0002-verification-is-artifact-scoped.md) +- [Aeneas and Charon integration](../open-questions/aeneas-charon-integration.md) +- [Source/model adequacy](../open-questions/source-model-adequacy.md) diff --git a/anneal/agent_docs/design/decisions/0004-invariants-support-all-property-kinds.md b/anneal/agent_docs/design/decisions/0004-invariants-support-all-property-kinds.md new file mode 100644 index 0000000000..487dbad048 --- /dev/null +++ b/anneal/agent_docs/design/decisions/0004-invariants-support-all-property-kinds.md @@ -0,0 +1,94 @@ + + +# 0004: Invariants support all property kinds + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +V1 explored type invariants under the name `isValid` and trait invariants under +the name `isSafe`. Those names suggest that one mechanism concerns validity and +the other concerns soundness. V2 must support soundness, but users also need +invariants for other properties: panic freedom, protocol correctness, +cryptographic conditions, resource bounds, and domains not designed yet. + +The exact taxonomy and notation for property kinds remain open. + +## Decision + +Both type invariants and trait invariants must support arbitrary property kinds. +Neither mechanism is intrinsically restricted to soundness or to one built-in +notion of safety. + +Soundness remains special and non-negotiable. Generalizing invariant mechanisms +does not permit another selected property to weaken, replace, or bypass the +obligations required for sound Rust. + +## Rationale + +Types and trait bounds are important abstraction boundaries regardless of the +property being composed. A common architecture avoids duplicating an invariant +system for every domain and leaves V2 extensible to properties whose proof +backends arrive later. Preserving soundness as a mandatory foundation keeps +extensibility from weakening the primary assurance. + +## Consequences + +- V2's invariant representation cannot hard-code type invariants as “validity” + or trait invariants as “soundness.” +- Implementations and consumers need a way to identify which property an + invariant establishes or assumes. +- Adding a new property domain must not require replacing the type- or trait- + invariant architecture. +- Initial V2 need not implement specialized proof backends for every possible + property kind; the architecture must leave room for them. +- The V1 names and enforcement mechanisms are not accepted by this decision. + +## Alternatives considered + +### Restrict both invariant forms to soundness + +This would require parallel mechanisms to express the same abstraction pattern +for other correctness properties. + +### Reserve type invariants for validity and trait invariants for soundness + +The distinction follows V1 terminology rather than a fundamental difference in +where property-carrying invariants are useful. + +### Defer extensibility until another property backend exists + +That risks embedding soundness-specific assumptions in interfaces which are +difficult to generalize later. + +## Deferred questions + +- What are property kinds called and how are they declared or selected? +- How are type invariants established, invalidated, opened, and re-established? +- How are trait invariants enforced at implementation sites and made available + through a bound? +- How does Anneal integrate invariant access with Rust's existing `unsafe` + machinery or an Anneal-specific parallel analysis? +- How are dependencies and cycles between property kinds represented? +- What should replace the V1 `isValid` and `isSafe` syntax? + +## Evidence + +- The project author explicitly required both type invariants and trait + invariants to support arbitrary property kinds. +- Experience with V1 showed that its names and partial enforcement did not + express this general architecture; see [V1 lessons](../../history/v1-lessons.md). + +## Links + +- [Contracts and invariants](../open-questions/contracts-and-invariants.md) +- [Property kinds and outcomes](../open-questions/property-kinds-and-outcomes.md) +- [Rust safety integration](../open-questions/rust-safety-integration.md) +- [Design principles](../principles.md) diff --git a/anneal/agent_docs/design/decisions/0005-incremental-adoption-supports-prose-justifications.md b/anneal/agent_docs/design/decisions/0005-incremental-adoption-supports-prose-justifications.md new file mode 100644 index 0000000000..ffe9df39c3 --- /dev/null +++ b/anneal/agent_docs/design/decisions/0005-incremental-adoption-supports-prose-justifications.md @@ -0,0 +1,99 @@ + + +# 0005: Incremental adoption supports prose justifications + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +Real Rust codebases already justify unsafe operations with prose such as +`// SAFETY:` comments. Requiring every relevant obligation to be formalized and +proved before Anneal provides any value would make adoption all-or-nothing. +Conversely, silently treating prose as a machine proof would make Anneal's +assurance misleading. + +The relationship between Anneal property tracking and Rust's existing `unsafe` +machinery remains an open design question, but incremental adoption is a +requirement under either architecture. + +## Decision + +Anneal must support an incremental-adoption mechanism in which selected formal +proof obligations may temporarily be represented by prose safety +justifications. + +Every such substitution is an explicit, auditable trust assumption. Anneal +must not report or consume it as if it were a completed machine-checked proof, +and a user must be able to discover it when evaluating the resulting assurance. + +This record requires the capability; it does not decide its syntax, which +obligations may use it, or the success semantics of a command that encounters +one. + +## Rationale + +Incremental adoption lets users formalize high-value portions of an existing +codebase without first rewriting every safety comment. Making the remaining +human reasoning explicit preserves honest claims and provides a measurable path +toward a fully formal result. + +## Consequences + +- Anneal needs a durable association between a prose justification and the + obligation it stands in for. +- Trust reports must expose which obligations rely on prose rather than a + completed proof; how the final ledger categorizes those assumptions remains + open. +- Results containing prose justifications are conditional on their correctness. +- Tooling should make it possible to find and reduce the remaining prose + obligations over time. +- Integration with familiar Rust comments is possible but not mandated by this + record. + +## Alternatives considered + +### Require complete formalization before running Anneal + +This gives a simple final state but does not support the required path for +adopting Anneal in an existing codebase. + +### Treat every unproved obligation as an unrestricted axiom + +This loses the connection to the relevant Rust operation and obscures the +different reasons that facts remain trusted. + +### Silently skip obligations without proofs + +That would make success impossible to interpret and would violate the need for +an auditable trust boundary. + +## Deferred questions + +- What syntax associates prose with an Anneal obligation? +- Which obligations may use prose and under which command or policy? +- Does a result with prose assumptions exit successfully as “conditionally + checked,” or use another status distinct from “verified”? +- How are review, ownership, expiry, and migration of prose assumptions tracked? +- How should this mechanism build on Rust `unsafe` blocks, safety comments, + lints, and possible future language features? + +## Evidence + +- The project author required some form of prose safety justification to stand + in for selected Anneal proofs during incremental adoption. +- Existing Rust practice already locates human safety arguments near unsafe + operations, providing a migration source even though prose is not itself a + proof. + +## Links + +- [The TCB is explicit and shrinkable](0006-the-tcb-is-explicit-and-shrinkable.md) +- [Trust and incremental adoption](../open-questions/trust-and-incremental-adoption.md) +- [Rust safety integration](../open-questions/rust-safety-integration.md) diff --git a/anneal/agent_docs/design/decisions/0006-the-tcb-is-explicit-and-shrinkable.md b/anneal/agent_docs/design/decisions/0006-the-tcb-is-explicit-and-shrinkable.md new file mode 100644 index 0000000000..83a9c2fed4 --- /dev/null +++ b/anneal/agent_docs/design/decisions/0006-the-tcb-is-explicit-and-shrinkable.md @@ -0,0 +1,122 @@ + + +# 0006: The TCB is explicit and shrinkable + +- **Status:** Accepted +- **Date:** 2026-07-17 + +## Context + +Anneal cannot initially prove every layer on which a Rust execution depends. +Primitive unsafe operations, compiler intrinsics, FFI, assembly, the +verification toolchain, and hardware all introduce facts that may have to be +trusted. Hiding those assumptions behind a successful command would make the +result impossible to audit. + +At the same time, treating today's body-unmodeled operations as a permanent +semantic boundary would prevent future work from replacing them with formal +models. For example, a formal ISA model could eventually make some assembly +transparent. + +## Decision + +Anneal V2 will reduce unproved operational semantics to a small, explicit set +of trusted leaves and will expose the assumptions on which a result depends. +The TCB is an auditable boundary, not an implicit promise. + +Initially, trusted semantic leaves are expected to include some unsafe standard +library functions and intrinsics, raw-pointer dereferences, FFI, and inline or +external assembly. Approved axioms and prose justifications must remain visible +as unproved assumptions. Incomplete proofs must remain visible as outstanding +obligations; whether a particular command mode blocks on or conditionally +admits them remains open. None may masquerade as verified facts. + +The architecture must permit a trusted leaf or platform assumption to be +replaced by a more detailed formal model later. A fully adopted codebase should +reserve axioms for genuinely external semantics, although the boundary of +“external” can shrink as new models become available. + +This decision does not claim that Anneal's complete practical TCB is initially +small. The compiler, translators, proof checker, platforms, and hardware remain +part of the end-to-end TCB until independently justified. “Small” applies first +to the explicit set of trusted program-semantic leaves. + +## Rationale + +A small and inspectable trusted semantic leaf set, together with an explicit +account of the broader end-to-end TCB, lets a user understand exactly what an +Anneal result entitles them to believe. Making the boundary replaceable +supports stronger assurance over time without requiring the initial +implementation to formalize the Rust compiler, every ISA, and every foreign +system before it is useful. + +## Consequences + +- Verification results are relative to the correctness of their recorded + trusted leaves and platform assumptions. +- Anneal needs a TCB audit ledger which includes axioms and unfinished + obligations, not merely a binary success indicator. +- The ledger must ultimately account for relevant Anneal, Aeneas, Charon, + rustc, LLVM, host-hardware, and target-hardware assumptions; its exact schema + is not fixed here. +- Standard-library support may use the same axiom-authoring machinery exposed + for genuinely external user semantics. +- Replacing an axiom with a proof or a leaf with a model must reduce, rather + than merely relocate invisibly, the reported trust boundary. +- Anneal authors are responsible for the adequacy of built-in soundness + preconditions on axiomatic unsafe leaves. + +## Alternatives considered + +### Prove every leaf before V2 can be useful + +This would postpone practical verification until numerous independent compiler, +library, platform, and hardware models exist. + +### Trust arbitrary body-unmodeled functions without reporting them + +This would verify callers only relative to hidden assumptions and invite users +to overstate the result. + +### Make the initial leaf boundary permanent + +That would prevent stronger future models from reducing the TCB and would make +implementation expedience part of Anneal's long-term assurance definition. + +## Deferred questions + +- What is the exact TCB audit-ledger schema and output format? +- Which assumptions cause `cargo anneal verify` to fail, succeed conditionally, + or succeed with warnings? +- Which initial leaves are axiomatized by Anneal, Aeneas, a platform package, or + a user? +- Who authors and distributes FFI contracts: library consumers, upstream + library authors, or both? +- How are toolchain, host, target, and hardware identities represented? +- Which formal Rust, allocator, ISA, concurrency, and foreign-language models + should replace trusted leaves first? + +## Evidence + +- The project author defined V2's long-term direction as reducing the TCB to a + small explicit collection of trusted leaves while preserving the option to + model those leaves later. +- The project author identified the TCB audit log as an important user-facing + capability and required axioms and not-yet-proven specifications to appear in + it. +- The requested trust inventory includes Anneal's dependencies and both host + and target hardware, even though its exact schema remains open. + +## Links + +- [Verification is artifact-scoped](0002-verification-is-artifact-scoped.md) +- [Incremental adoption supports prose](0005-incremental-adoption-supports-prose-justifications.md) +- [Trust and incremental adoption](../open-questions/trust-and-incremental-adoption.md) +- [Source/model adequacy](../open-questions/source-model-adequacy.md) +- [Verification result and trust](../result-and-trust.md) diff --git a/anneal/agent_docs/design/decisions/README.md b/anneal/agent_docs/design/decisions/README.md new file mode 100644 index 0000000000..a231e49d52 --- /dev/null +++ b/anneal/agent_docs/design/decisions/README.md @@ -0,0 +1,60 @@ + + +# Design decisions + +This directory records Anneal V2 design decisions whose alternatives matter to +future work. A decision record says what was decided, why that choice follows +from Anneal's principles, and which questions it deliberately leaves open. + +Decision records complement, rather than replace, the other design documents: + +- [Principles](../principles.md) supplies reusable rules for evaluating design + alternatives. +- [Settled requirements](../settled-requirements.md) collects the constraints + that an acceptable design must satisfy. +- [Open questions](../open-questions/README.md) tracks design spaces in which no + choice has yet been made. + +An accepted record is normative until it is superseded. Historical evidence, +the V1 implementation, issues, and pull requests do not override it. If new +evidence changes a decision, add a new record that names the record it +supersedes instead of silently rewriting the old rationale. Small corrections +which do not change the decision may be made in place. + +## Statuses + +- **Proposed:** available for discussion, but not binding. +- **Accepted:** a current project commitment. +- **Rejected:** considered and deliberately not adopted. +- **Superseded:** retained as history, with a link to its replacement. + +## Authoring a record + +Copy [the template](0000-template.md), allocate the next four-digit number, and +keep the decision as narrow as the available evidence permits. In particular: + +- distinguish required outcomes from possible implementations; +- derive the rationale from project principles rather than precedent alone; +- list costs and constraints as well as benefits; +- move unresolved choices to **Deferred questions**; and +- link the evidence that made the decision possible. + +Do not turn a promising direction, an implementation trend, or a V1 design into +an accepted decision without explicit project agreement. + +## Accepted decisions + +| Record | Decision | +| --- | --- | +| [0001](0001-v2-is-a-clean-room-redesign.md) | V2 is a clean-room, ground-up redesign. | +| [0002](0002-verification-is-artifact-scoped.md) | A verification claim initially covers one fixed compilation artifact. | +| [0003](0003-expanded-generated-rust-is-input.md) | Expanded, generated Rust is verification input, not trusted source. | +| [0004](0004-invariants-support-all-property-kinds.md) | Type and trait invariants support arbitrary property kinds. | +| [0005](0005-incremental-adoption-supports-prose-justifications.md) | Incremental adoption supports explicit, audited prose justifications. | +| [0006](0006-the-tcb-is-explicit-and-shrinkable.md) | The trusted computing base is explicit, auditable, and shrinkable. | diff --git a/anneal/agent_docs/design/open-questions/README.md b/anneal/agent_docs/design/open-questions/README.md new file mode 100644 index 0000000000..ca5e098588 --- /dev/null +++ b/anneal/agent_docs/design/open-questions/README.md @@ -0,0 +1,76 @@ + + +# Open design questions + +This directory records consequential Anneal V2 design questions that have not +yet been decided. It exists to preserve the reasoning behind candidate designs +without turning the current implementation, Anneal V1, an issue, or a passing +conversation into policy by accident. + +An open question is not a blank slate. Each document begins with a compact +table linking the requirements and accepted decisions that constrain it, then +states only the topic-specific implications needed to evaluate candidates. +Those tables are indexes, not independent normative summaries. Agents and +humans may explore the remaining design space, but must not silently relax the +linked constraints. Conversely, candidates and current leanings are evidence +and working hypotheses, not commitments. + +The normative [project principles](../principles.md), +[settled requirements](../settled-requirements.md), and +[accepted decisions](../decisions/README.md) take precedence over this ledger. +Anneal V1 is a source of experience, not a default architecture for V2. When a +choice is accepted, record it in a decision record and update or close the +corresponding question here rather than merely changing an implementation. + +## Index + +| Area | Central question | +| --- | --- | +| [Property kinds and outcomes](property-kinds-and-outcomes.md) | How should Anneal represent distinct guarantees, execution outcomes, dependencies, and user selection without baking in a premature taxonomy? | +| [Rust safety integration](rust-safety-integration.md) | Which obligations should reuse Rust's `unsafe` machinery, and which require a richer Anneal-owned tracking system? | +| [Contracts and invariants](contracts-and-invariants.md) | How should function contracts, type invariants, and trait invariants be stated, enforced, and made available to callers? | +| [Source/model adequacy](source-model-adequacy.md) | How can proofs about a model that assumes soundness establish the soundness of the source program itself? | +| [Memory, resources, and effects](memory-resources-and-effects.md) | Where can unsafe implementations close to simple functional models, and where must resource or effect semantics remain visible? | +| [Trust and incremental adoption](trust-and-incremental-adoption.md) | How should axioms, incomplete proofs, prose justifications, and the audit ledger affect the meaning of verification? | +| [Aeneas and Charon integration](aeneas-charon-integration.md) | What information and machinery should Anneal consume, extend upstream, or own itself? | +| [Proof authoring and user experience](proof-authoring-and-user-experience.md) | What proof surface can eventually serve ordinary Rust engineers, formal-methods specialists, and agents without sacrificing rigor? | + +These areas intentionally overlap. A proposed answer should follow the related +links and account for its consequences elsewhere. In particular, choices about +property kinds affect Rust integration, contracts, trust reporting, and the +command-line interface; choices about source adequacy affect the Aeneas/Charon +boundary and the memory model. + +## How to update this ledger + +This section is the shared procedure for every page in this directory; +individual pages should add only topic-specific criteria and experiments. + +When adding evidence or a candidate design: + +1. State which settled constraints it preserves. +2. Distinguish observed facts from inferences and preferences. +3. Explain the user-visible and trusted-computing-base consequences. +4. Record dependencies on Rust, Lean, Aeneas, Charon, compilers, or hardware. +5. Prefer a small experiment or counterexample over confidence based only on + architectural taste. + +When deciding a question: + +1. Derive the decision from the project's principles and concrete evidence. +2. Add a decision record with alternatives and consequences. +3. Update every affected document, including settled requirements and current + state where appropriate. +4. Leave enough historical context here to explain what was learned, while + clearly marking the question or sub-question as resolved. + +Temporary disagreements about terminology should not be preserved as design +questions after the underlying meaning is understood. This ledger tracks real +choices that could change Anneal's guarantees, architecture, or user +experience—not conversational cleanup. diff --git a/anneal/agent_docs/design/open-questions/aeneas-charon-integration.md b/anneal/agent_docs/design/open-questions/aeneas-charon-integration.md new file mode 100644 index 0000000000..0df6ba07ba --- /dev/null +++ b/anneal/agent_docs/design/open-questions/aeneas-charon-integration.md @@ -0,0 +1,151 @@ + + +# Aeneas and Charon integration + +**Status:** Open design discussion. + +Anneal is intended to orchestrate and extend Charon's compiler extraction and +Aeneas's Lean translation. V2 must decide which interfaces to consume, which +capabilities to add upstream, and which temporary adaptations Anneal should +own. These are engineering choices governed by semantic fidelity, +maintainability, and user experience rather than a categorical ownership rule. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-001](../settled-requirements.md#anneal-req-001-v2-is-a-clean-room-redesign), [decision 0001](../decisions/0001-v2-is-a-clean-room-redesign.md) | V1 integration techniques carry no presumption into V2. | +| [ANNEAL-REQ-017](../settled-requirements.md#anneal-req-017-initial-claims-are-artifact-scoped), [decision 0002](../decisions/0002-verification-is-artifact-scoped.md) | Integration must identify one compiler-resolved compilation subject. | +| [ANNEAL-REQ-018](../settled-requirements.md#anneal-req-018-generated-rust-is-analyzed-input), [decision 0003](../decisions/0003-expanded-generated-rust-is-input.md) | Expanded generated Rust which enters the artifact is analyzed input. | +| [ANNEAL-REQ-019](../settled-requirements.md#anneal-req-019-coverage-adequacy-is-enforced) | Every potentially invalid operation in the reported coverage envelope must be reconciled with complete obligation coverage. | +| [ANNEAL-REQ-021](../settled-requirements.md#anneal-req-021-results-carry-an-audit-ledger) | Results must record the relevant translator, compiler, and proof-tool identities and gaps. | +| [ANNEAL-REQ-025](../settled-requirements.md#anneal-req-025-existing-proof-machinery-is-preferred), [ANNEAL-REQ-026](../settled-requirements.md#anneal-req-026-upstream-evolution-is-in-scope) | Suitable maintained machinery is preferred, and upstream changes are available when they are the best engineering choice. | + +Topic-specific implications: + +- The compiler-resolved artifact must remain authoritative. Any source scanner, + annotation index, generated proof, or sidecar manifest must reconcile with + it rather than silently creating a shadow view of the Rust program. +- No requirement categorically assigns a capability upstream or downstream. + Ownership depends on semantic fidelity, interface robustness, maintenance + burden, and user experience. +- Direct LLBC consumption, structured compiler metadata, Lean syntax + extensions, and downstream adapters all remain candidates. Fragile textual + rewriting is evidence that an interface may be missing, not a prohibited + implementation technique. + +V1's duplicate progress and conditional-correctness proofs are evidence in +favor of experimenting with Aeneas's WP specifications and `step`/`step*` +tactics. They do not settle the proof architecture. + +## Information boundary + +LLBC is a natural semantic input because Charon has already resolved much of +Rust's syntax and types. Anneal annotations also need to bind source intent to +the exact items, fields, operations, and calls that the compiler verifies. +Depending only on a parallel `syn` parse risks creating a shadow view that +disagrees after macro expansion, `cfg` processing, name resolution, or +desugaring. + +One candidate is a compiler-resolved annotation or index mode in Charon. It +could expose expanded annotations, stable-within-artifact item identifiers, +signatures, source provenance, monomorphized or resolved call metadata, unsafe +operations, field accesses, and links to LLBC declarations. A source scanner +could remain a bootstrap or authoring aid but would have to reconcile exactly +against this authoritative index. + +This candidate has not been accepted. Its motivation is to avoid silent skew, +support generated code, find every obligation, improve diagnostics, and reduce +dependence on generated Lean names. We still need to determine which facts are +already in LLBC, which should be added to Charon, and which Anneal can derive +reliably. + +## Questions to resolve + +### What should Charon expose? + +- How are annotations preserved through expansion and lowering? +- Which identifiers remain stable enough for proof artifacts, incremental + builds, and diagnostics? +- Can fields, unsafe operations, drop glue, trait dispatch, closures, and + compiler-generated items be indexed uniformly? +- Does Anneal need MIR-level facts that LLBC intentionally omits? +- How are source spans represented for macro-generated and desugared code? +- Can Charon report unsupported or erased constructs so Anneal fails closed? +- At what compiler phase must extraction occur to avoid transformations that + assume undefined behavior cannot happen? + +The last question is part of the adequacy problem described in +[source/model adequacy](source-model-adequacy.md). + +### What should Aeneas expose or own? + +- Can unsafe leaves be represented within Aeneas's WP semantics with explicit + guards and resource effects? +- Which distinctions among return, panic, unwind, abort, divergence, undefined + operation, and modeling failure should Aeneas preserve? +- How can multiple property obligations share symbolic execution through + `step` and `step*` without forcing every domain into the same logic? +- What changes are needed for separation-logic objects or capabilities whose + use must remain affine or linear? +- Should Aeneas emit structured proof metadata alongside Lean definitions? +- Can generated definitions expose stable theorem interfaces rather than + implementation-specific names? +- How does unsafe and separation-logic work available or proposed in the + relevant Aeneas revision relate to an Anneal-owned short-term pointer model? + +Generic resource machinery may belong in Lean libraries, Rust-specific +semantics in Aeneas, and orchestration in Anneal, but that division is only a +working possibility. See [memory, resources, and effects](memory-resources-and-effects.md). + +### How does Anneal attach its contracts? + +Candidate techniques include: + +- extend LLBC with elaborated contracts and invariant declarations; +- provide Aeneas a structured sidecar manifest keyed by Charon identifiers; +- extend Aeneas lowering so proposition-valued contract arguments appear in + generated functions; +- generate sidecar WP theorems for every indexed call; +- inject stable Lean macros or syntax that elaborate against generated + declarations; and +- validate generated Lean against an independent obligation manifest. + +The choice should be based on completeness, auditability, compatibility with +Aeneas tactics, diagnostic quality, and maintenance cost. “No textual +post-processing ever” is not a principle, but fragile search-and-replace over +generated code is strong evidence that an upstream interface is missing. + +### How are versions and downstream adaptations managed? + +- Does Anneal track released Aeneas/Charon versions, pinned revisions, or a + maintained fork? +- What compatibility contract can upstream realistically offer? +- How do proof artifacts record the exact translator and standard-library + versions they depend on? +- When should experimental work live downstream before an upstream API is + proposed? +- Who owns tests demonstrating that an upstream change preserves Anneal's + semantic assumptions? + +## Evaluation criteria + +A durable integration must make the compiler-resolved artifact authoritative, +detect annotation or coverage skew, preserve all semantics needed for claimed +properties, and give proof authors stable interfaces. It should reuse upstream +machinery, avoid imposing Anneal-only complexity on all Aeneas users, and leave +a credible path for temporary downstream work to mature upstream. + +Useful experiments include a proc-macro-generated unsafe call with an +annotation, a generic trait call resolved after monomorphization, an invariant +on a compiler-generated field access path, shared WP execution for two property +kinds, and a resource assertion that Lean cannot duplicate. + +The effect on ordinary users is discussed in +[proof authoring and user experience](proof-authoring-and-user-experience.md). diff --git a/anneal/agent_docs/design/open-questions/contracts-and-invariants.md b/anneal/agent_docs/design/open-questions/contracts-and-invariants.md new file mode 100644 index 0000000000..58733f32c4 --- /dev/null +++ b/anneal/agent_docs/design/open-questions/contracts-and-invariants.md @@ -0,0 +1,176 @@ + + +# Contracts and invariants + +**Status:** Open design discussion. + +Function contracts, type invariants, and trait invariants are the principal +units by which local proofs become reusable facts. Their semantic roles are +durable, but their syntax, enforcement mechanisms, and relationship to Rust's +types remain open for V2. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational), [ANNEAL-REQ-006](../settled-requirements.md#anneal-req-006-soundness-specifications-produce-adequate-obligations) | User contracts cannot weaken or erase Rust soundness obligations. | +| [ANNEAL-REQ-009](../settled-requirements.md#anneal-req-009-local-contract-obligations), [ANNEAL-REQ-010](../settled-requirements.md#anneal-req-010-local-results-compose-globally) | Item contracts must support local proof and reusable global composition. | +| [ANNEAL-REQ-012](../settled-requirements.md#anneal-req-012-property-dependencies) | Contracts and invariants must express dependencies among property kinds, including cycles treated soundly. | +| [ANNEAL-REQ-014](../settled-requirements.md#anneal-req-014-type-invariants-support-arbitrary-property-kinds), [ANNEAL-REQ-015](../settled-requirements.md#anneal-req-015-trait-invariants-support-arbitrary-property-kinds), [decision 0004](../decisions/0004-invariants-support-all-property-kinds.md) | Both type and trait invariants support arbitrary property kinds, with their respective establishment and use obligations enforced. | +| [ANNEAL-REQ-016](../settled-requirements.md#anneal-req-016-contracts-distinguish-semantic-roles) | The model must distinguish soundness obligations from ordinary functional preconditions and other property roles. | +| [ANNEAL-REQ-019](../settled-requirements.md#anneal-req-019-coverage-adequacy-is-enforced) | Whatever contract encoding is chosen must not omit a potentially invalid operation within the reported coverage envelope. | + +Topic-specific implications: + +- A safe API cannot make undefined behavior depend on an extra unchecked + obligation of its safe caller. It may still state conditional functional or + other guarantees without turning their conditions into soundness + preconditions. +- Built-in soundness contracts are answerable to Rust's semantics. A + user-defined correctness axiom records the user's intended property; Anneal + can enforce and report it but cannot supply its real-world intent. +- V1's `isValid`, `isSafe`, and indentation-sensitive proof syntax are neither + enforcement mechanisms nor syntax commitments for V2. + +## Function contracts + +### Safety contracts versus general contracts + +Rust's source syntax does not distinguish a soundness precondition from a +precondition for panic freedom, a functional result, or a protocol. V2 needs a +semantic distinction even if the surface syntax is shared. + +Questions include: + +- Does every clause name its property kind explicitly, inherit one from its + declaration, or elaborate to a typed Lean-level obligation? +- How does a safe function express “if `x > 0`, the result has property P” + without suggesting that `x <= 0` may cause undefined behavior? +- Can a single precondition support multiple postconditions or property kinds? +- How are frame conditions, exceptional postconditions, trace conditions, and + resource transfer represented? +- Are contracts attached to source functions, monomorphized instances, trait + methods, function values, or compiler-resolved items with quantified + generics? +- Which contract facts become part of a separately compiled crate's + verification interface? + +The surface should make an accidental weakening of soundness obligations hard +to overlook while remaining usable for general correctness claims. + +### Contracts as types or sidecar theorems + +One candidate lowers a Rust function with Anneal preconditions to a Lean +function whose proposition-valued arguments must be supplied at every call. +This closely resembles an extension to the type system and makes an omitted +proof ill-typed. Another keeps Aeneas's ordinary function model and proves +sidecar theorems showing that every call satisfies the relevant contract. The +latter aligns more directly with existing Aeneas WP machinery. + +This is primarily a representation and enforcement choice. Either is +acceptable only if Anneal can establish complete coverage of all applicable +calls. The deeper circularity in using a soundness-dependent model is treated +in [source/model adequacy](source-model-adequacy.md). + +Open details include higher-order calls, recursion, dynamic dispatch, trait +resolution, closures, foreign calls, and how proof obligations survive +monomorphization or separate compilation. + +## Type invariants + +A type invariant describes facts that valid uses of a value may rely on. It may +support soundness—for example, initialized storage or a valid pointer +relationship—or another property such as a cryptographic representation +invariant or resource bound. + +Questions include: + +- Is an invariant a proposition over an abstract value, a resource assertion, + a family indexed by property kind, or an interface that can provide multiple + forms of evidence? +- At which points must it hold: all observable safe states, function + boundaries, borrow boundaries, suspension points, panic edges, or some + declared subset? +- How is an invariant opened temporarily, and what capability guarantees that + it is restored before control escapes through return, panic, cancellation, + or destruction? +- Which reads require proof that the invariant holds, and which writes require + proof that it is re-established? +- How do interior mutability, aliasing, pinning, drop, partial initialization, + unions, and concurrency change the proof rules? +- Can a type carry several invariants with dependencies between property kinds? + +Enforcement might build on Rust unsafe fields or use Anneal-specific analysis; +see [Rust safety integration](rust-safety-integration.md). Resource-bearing +invariants cannot be flattened into freely duplicable propositions; see +[memory, resources, and effects](memory-resources-and-effects.md). + +## Trait invariants + +The durable idea behind V1's `isSafe` is that an implementation supplies an +invariant promised by the trait, and generic code consumes that invariant from +a known bound. V2 must make both halves enforceable. + +Questions include: + +- Does the trait declare one invariant per property kind, one structured family + of invariants, or named obligations with explicit dependencies? +- Which implementations require a proof: unsafe implementations only, all + implementations of an annotated trait, or a set selected by the property? +- How is evidence made available in a generic context with `T: Trait`? +- How are associated types, constants, generic associated types, supertraits, + negative reasoning, specialization, and trait objects handled? +- Does dynamic dispatch carry a proof dictionary, rely on a sidecar theorem for + the vtable, or elaborate through another mechanism? +- How do auto traits and compiler-generated implementations participate? +- Can an implementation assume other property-kind obligations while proving + its own, and how are cycles certified? + +The answer must prevent an implementation from entering verified code without +its declared obligations while avoiding repeated proofs at every generic use. + +## Specification adequacy and evolution + +Lean can prove a weak or vacuous proposition. For non-axiomatic soundness +specifications, Anneal must connect generated obligations to modeled primitive +semantics strongly enough to guarantee adequacy; human review alone is not the +end state. How it does so is open. + +For user-defined properties, specification intent ultimately comes from the +user. Anneal can still help by detecting unused clauses, vacuous implications, +inconsistent assumptions, or contracts that do not cover executions, but such +checks do not create an external ground truth. + +Contracts also need an evolution story: + +- What changes are compatible for downstream proofs? +- Can implementation details and Aeneas-generated names remain hidden behind a + stable verification interface? +- How are property-kind dependencies versioned? +- Can automated proof repair absorb small Rust refactorings without concealing + a semantic contract change? + +## Evaluation criteria and examples + +A viable design must preserve safe Rust's soundness promise, enforce every +declared implementation obligation, expose exactly the facts a caller may use, +respect resource semantics, and compose across generics and crates. + +Representative experiments should cover: + +- a safe API around a raw-pointer representation; +- a safe function with a conditional functional guarantee but no caller + soundness obligation; +- a type whose field invariant is temporarily broken and restored; +- an unsafe trait with generic and dynamically dispatched consumers; +- a trait invariant for a property other than soundness; and +- mutually dependent type, trait, and callee properties. + +Proof surface and diagnostics are discussed in +[proof authoring and user experience](proof-authoring-and-user-experience.md). diff --git a/anneal/agent_docs/design/open-questions/memory-resources-and-effects.md b/anneal/agent_docs/design/open-questions/memory-resources-and-effects.md new file mode 100644 index 0000000000..618f709c90 --- /dev/null +++ b/anneal/agent_docs/design/open-questions/memory-resources-and-effects.md @@ -0,0 +1,159 @@ + + +# Memory, resources, and effects + +**Status:** Open design discussion. + +Aeneas obtains a simple functional model for a large subset of Rust by using +the borrow checker's discipline. Unsafe Rust, interior mutation, allocators, +concurrency, I/O, and similar features can require spatial, temporal, or +effectful reasoning. Anneal's central opportunity is to combine the simple +functional domain with enough resource-aware machinery to verify unsafe code +without imposing a full heap logic on every proof. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-003](../settled-requirements.md#anneal-req-003-general-rust-use-cases) | The architecture must accommodate Rust domains whose essential memory, concurrency, or external-effect semantics cannot be erased. | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational) | Simplicity cannot weaken the soundness foundation of a source-level claim. | +| [ANNEAL-REQ-007](../settled-requirements.md#anneal-req-007-the-memory-model-is-conservative) | Any Anneal-owned memory model must conservatively formalize the normative Rust guarantees it claims. | +| [ANNEAL-REQ-008](../settled-requirements.md#anneal-req-008-resource-semantics-are-preserved) | Ownership, provenance, initialization, permissions, and protocol resources must retain their usage discipline in Lean. | +| [ANNEAL-REQ-010](../settled-requirements.md#anneal-req-010-local-results-compose-globally) | Resource and effect reasoning must support abstraction boundaries whose established contracts are reusable by callers. | +| [ANNEAL-REQ-011](../settled-requirements.md#anneal-req-011-long-running-and-exceptional-behavior) | The model must support invariant-preserving infinite execution and sound panic, unwind, and recovery paths. | +| [ANNEAL-REQ-025](../settled-requirements.md#anneal-req-025-existing-proof-machinery-is-preferred), [ANNEAL-REQ-026](../settled-requirements.md#anneal-req-026-upstream-evolution-is-in-scope) | Suitable maintained machinery is preferred, but Anneal, Aeneas, Charon, Lean libraries, and Rust may evolve where needed. | + +Topic-specific implications: + +- Prefer the simplest abstraction that preserves every fact needed for the + claim. Pure value contracts are desirable when faithful, but purity is not + an independent objective. +- Operationally global state or history may be packaged behind local + capabilities, shared invariants, or abstract interfaces only if the proof + rules preserve its resource discipline. +- Robust contextual refinement at a safe boundary does not require literal + representation as a pure value transformer. Effectful, world-indexed, or + protocol interfaces remain available when a simpler boundary would erase + claim-relevant behavior. + +## Locality and abstraction closure + +Safe encapsulation demonstrates that unsafe implementation details can often +be hidden behind a safe interface: clients should not need to reason about the +entire program to use a well-designed abstraction soundly. Separation logic +recovers a related locality by splitting global state into composable resources. +Anneal should exploit this symmetry, but must not assume every abstraction can +be represented as a pure function on values. + +Open questions include: + +- What semantic condition shows that an unsafe implementation refines its safe + interface in every safe context? +- Which effects can close behind an existential representation invariant, and + which must remain in the public contract? +- Can allocator state, provenance history, concurrency protocols, and device + state be represented by local capabilities or shared invariants? +- When a fact is operationally global, what proof rules let a client use a + localized view without making the proof unsound? +- How are abstraction boundaries nested and composed across crates? + +The objective is not purity for its own sake. It is the simplest interface that +is faithful, compositional, understandable, and resilient to implementation +change. + +## Questions to resolve + +### What resource logic is required? + +- Which assertions must be affine, linear, persistent, fractional, or otherwise + controlled? +- How are allocation, initialization, validity, provenance, aliasing, + permissions, and lifetime represented? +- Which rules are generic separation-logic infrastructure and which encode + Rust-specific semantics? +- Can Aeneas's existing state and WP machinery host these assertions, or is a + new monad or logic required? +- How are resource assertions transferred through Aeneas's forward/backward + treatment of borrows? +- How do resource obligations appear in ordinary Lean goals and tactics without + letting users duplicate or discard them illegally? + +The design should reuse maintained Lean and Aeneas abstractions wherever they +fit. Reinvention remains possible when an existing abstraction cannot express +the needed guarantee or would impose unacceptable complexity. + +### Which effects remain visible? + +Representative domains include: + +- allocators and address reuse; +- I/O and interaction with an external environment; +- atomics, locks, threads, and scheduling; +- nondeterminism and randomness; +- panic, unwind cleanup, cancellation, and abort; +- volatile or memory-mapped operations; +- FFI and inline or out-of-line assembly; and +- long-running services and reactive protocols. + +For each, V2 must decide whether a boundary exposes a state transformer, an +effect trace, a WP, a protocol capability, a nondeterministic relation, or a +simpler derived contract. The answer may vary by property kind. A functional +result theorem may hide scheduling details that a deadlock theorem must retain. + +### How conservative is the memory model? + +Rust's operational guarantees are still largely written in prose and continue +to evolve. V2 must determine: + +- which normative documents and team decisions ground each axiom; +- how ambiguity is handled without accidentally claiming more than Rust + guarantees; +- when to ask the Rust project to clarify or change the reference; +- how target layout, ABI, compiler, and hardware assumptions enter the model; +- how provenance and aliasing rules are versioned; and +- how proofs remain useful as the model is refined. + +The authors' direct involvement with Rust's operational-semantics work makes +upstream clarification possible. It does not remove the need to expose current +assumptions in Anneal's trust ledger. + +### Where should the implementation live? + +Candidate arrangements include: + +- Aeneas owns general unsafe or separation-logic semantics and Anneal supplies + annotations and orchestration; +- Anneal temporarily owns a conservative pointer/layout layer that later moves + upstream; +- Lean libraries own generic resource machinery while Aeneas owns Rust + instantiations; and +- multiple semantic backends coexist behind a common contract interface. + +Changes should be upstream when they form reusable Aeneas or Charon +functionality and when the maintenance burden is acceptable. Shipping a sound +and auditable Anneal remains more important than an aesthetically perfect +ownership boundary. + +## Evaluation criteria + +A candidate must preserve resource usage rules, support modular composition, +state its relationship to normative Rust, and make exceptional and infinite +executions sound. It should keep simple safe-code proofs simple and reveal +complex machinery only where the claimed behavior needs it. It should also +allow the trusted model to shrink or become more precise without rewriting +unrelated user proofs. + +Useful experiments include a raw-pointer container that closes to a pure safe +API, an allocator whose capability must remain visible, a lock with a shared +invariant, panic during partially initialized construction, and an I/O protocol +whose functional return value alone is inadequate. + +See also [property kinds and outcomes](property-kinds-and-outcomes.md), +[contracts and invariants](contracts-and-invariants.md), and +[Aeneas and Charon integration](aeneas-charon-integration.md). diff --git a/anneal/agent_docs/design/open-questions/proof-authoring-and-user-experience.md b/anneal/agent_docs/design/open-questions/proof-authoring-and-user-experience.md new file mode 100644 index 0000000000..c8efa210fa --- /dev/null +++ b/anneal/agent_docs/design/open-questions/proof-authoring-and-user-experience.md @@ -0,0 +1,177 @@ + + +# Proof authoring and user experience + +**Status:** Open design discussion. + +Anneal's eventual audience includes ordinary Rust teams, formal-methods +specialists, and coding agents. The aspiration is that even early-career Rust +engineers can participate, potentially with AI assistance, while the resulting +claims remain rigorous and reviewable. The right source syntax, proof workflow, +and division of labor are matters for experimentation. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-001](../settled-requirements.md#anneal-req-001-v2-is-a-clean-room-redesign), [decision 0001](../decisions/0001-v2-is-a-clean-room-redesign.md) | V1's literate proof syntax is evidence, not a product commitment. | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational), [ANNEAL-REQ-021](../settled-requirements.md#anneal-req-021-results-carry-an-audit-ledger) | A smoother interface cannot weaken the formal claim or conceal its dependencies. | +| [ANNEAL-REQ-010](../settled-requirements.md#anneal-req-010-local-results-compose-globally) | Established abstraction contracts must be reusable without reopening private bodies. | +| [ANNEAL-REQ-022](../settled-requirements.md#anneal-req-022-incremental-adoption-supports-prose), [decision 0005](../decisions/0005-incremental-adoption-supports-prose-justifications.md) | The workflow must accommodate explicit, audited prose justifications during incremental adoption. | +| [ANNEAL-REQ-024](../settled-requirements.md#anneal-req-024-incompleteness-is-distinguishable-from-external-trust) | UX and diagnostics must not collapse unfinished proofs into intentional external trust. | +| [ANNEAL-REQ-025](../settled-requirements.md#anneal-req-025-existing-proof-machinery-is-preferred) | Suitable Lean and Aeneas machinery should be reused rather than rebuilt without a concrete benefit. | +| [ANNEAL-REQ-027](../settled-requirements.md#anneal-req-027-ordinary-rust-engineers-are-a-target-audience) | The eventual workflow must serve ordinary Rust engineers without sacrificing meaning or auditability. | + +Topic-specific implications: + +- Machine checking, not trust in a human- or AI-generated explanation, + establishes a formal claim. Assistance can change who writes a proof, but + not what counts as evidence. +- Proof interfaces should avoid needless dependence on generated names and + internal WP structure. That preference does not require hiding Lean or + Aeneas from expert users. +- Humans and agents should work from the same contracts, principles, and + result semantics even when their authoring interfaces differ. + +## Who authors what? + +Possible workflows include: + +- Rust engineers write contracts and proof-relevant explanations while agents + synthesize Lean proofs; +- agents propose both code and specifications, with humans reviewing intent and + Lean checking proof correctness; +- formal-methods specialists publish reusable contracts, tactics, and models + consumed by ordinary teams; +- library authors ship verified interfaces that downstream users consume + without seeing implementation proofs; and +- humans write all proof material directly for especially sensitive code. + +V2 should not assume one universal workflow. It should identify which artifacts +require human judgment—especially the intended meaning of user-defined +specifications—and which can be generated or checked mechanically. + +Open questions include: + +- What must a Rust author understand about Lean, LLBC, Aeneas WP semantics, and + memory resources? +- Which proof steps are stable enough for agents to regenerate automatically? +- How does review distinguish a semantic specification change from proof repair + after a refactor? +- Can organizations require human approval of axioms or soundness contracts + while automating ordinary proofs? +- How are proof ownership and maintenance responsibility recorded? + +## Surface syntax and artifact layout + +Candidate locations include Rust attributes, doc comments, inline comments, +adjacent Lean files, generated proof modules with checked-in overlays, or a +combination. Each has different consequences for macro expansion, IDE support, +source control, Rust documentation, and proof reuse. + +Questions to resolve: + +- How are property kinds, preconditions, postconditions, type invariants, trait + invariants, exceptional behavior, and resource transfer written? +- Which parts use Rust-like syntax and which expose Lean terms? +- Can specifications remain near Rust while larger proofs live in ordinary Lean + modules? +- How does a proof refer to compiler-resolved items without depending on + unstable generated names? +- Are proofs checked in, generated on demand, cached as artifacts, or all three + under different policies? +- How are macro-generated items annotated or given contracts? +- Can source formatting and rustdoc ignore Anneal content cleanly? +- What is the migration path if syntax evolves rapidly during pre-alpha work? + +The compiler binding needed for these choices is discussed in +[Aeneas and Charon integration](aeneas-charon-integration.md). + +## Obligation presentation and diagnostics + +`cargo anneal verify` should help a Rust engineer understand what must be true +at the relevant source location. It remains open how much of the underlying +Lean goal and Aeneas state is exposed. + +Useful diagnostic capabilities may include: + +- a Rust-level explanation of the violated callee precondition; +- the property kind and transitive dependency that generated it; +- the exact compiler-resolved operation, including generated code provenance; +- relevant assumptions, type or trait invariants, and owned resources; +- the normal, panic, unwind, or other path on which the obligation occurs; +- a minimal Lean goal for expert debugging; +- an audit distinction among failed, unsupported, incomplete, axiomatic, and + prose-justified obligations; and +- machine-readable output for IDEs and agents. + +Questions include whether Anneal should synthesize counterexamples, symbolic +traces, suggested invariants, or proof skeletons; how it avoids presenting an +unsoundly simplified explanation; and how diagnostics remain stable when +Aeneas internals change. + +## Verification loop + +The desired workflow should feel proportionate to ordinary Rust development: +fast feedback for local changes, a stronger reproducible check in CI, and a +clear audit artifact for review or release. Design work is needed for: + +- incremental extraction and Lean recompilation; +- caching keyed by the exact Cargo artifact and toolchain; +- checking selected property kinds and their dependencies; +- distinguishing quick local checking from release assurance without + overloading “verified”; +- editing support that navigates between Rust obligations and Lean proofs; +- proof repair when generated definitions change; and +- reducing irrelevant churn in error messages and audit logs. + +The command success policy is part of +[trust and incremental adoption](trust-and-incremental-adoption.md), while the +semantics of selected properties are covered in +[property kinds and outcomes](property-kinds-and-outcomes.md). + +## Abstraction and leakage + +Some Aeneas concepts will inevitably be useful to proof authors. The open +question is which become stable Anneal concepts and which remain expert escape +hatches. + +Candidate layers include: + +1. Rust-oriented contracts and generated obligations for common proofs. +2. Reusable Anneal tactics and libraries that expose selected WP and resource + concepts. +3. Full Lean and Aeneas access for specialists and novel domains. + +This layering is only a candidate. It must not cause the convenient layer to +hide assumptions or make advanced properties impossible. Likewise, forcing all +users to manipulate generated forward/backward functions or raw separation +logic would undermine the broad-adoption goal if stable abstractions can avoid +it. + +## Evaluation criteria and experiments + +Evaluate workflows by semantic clarity, error discoverability, proof stability, +auditability, adoption cost, and the ability of both humans and agents to make +safe changes. Raw proof length or the absence of visible Lean is not by itself a +measure of usability. + +Experiments should include: + +- a new Rust graduate repairing a failed call-site proof with guided tooling; +- an agent updating a proof after a small implementation refactor without + changing the contract; +- a specialist adding a new resource-aware property domain; +- migration from `// SAFETY:` prose to a formal proof; +- review of a PR that changes both a contract and its proof; and +- downstream use of a verified generic library without dependence on generated + Aeneas names. + +The governing contract and invariant questions are recorded in +[contracts and invariants](contracts-and-invariants.md). diff --git a/anneal/agent_docs/design/open-questions/property-kinds-and-outcomes.md b/anneal/agent_docs/design/open-questions/property-kinds-and-outcomes.md new file mode 100644 index 0000000000..0c14ee4b3e --- /dev/null +++ b/anneal/agent_docs/design/open-questions/property-kinds-and-outcomes.md @@ -0,0 +1,164 @@ + + +# Property kinds and execution outcomes + +**Status:** Open design discussion. + +Anneal must reason about Rust soundness and also support properties such as +panic freedom, deadlock freedom, cryptographic correctness, protocol +correctness, and resource bounds. Rust's present `safe`/`unsafe` distinction +does not identify these different kinds of obligation. V2 needs an extensible +model, but adopting a taxonomy too early would constrain domains that have not +yet been explored. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-002](../settled-requirements.md#anneal-req-002-general-properties), [ANNEAL-REQ-004](../settled-requirements.md#anneal-req-004-extensibility-before-breadth) | The architecture must admit arbitrary user-defined property domains without requiring all specialized backends initially. | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational) | Soundness is a mandatory semantic foundation, not an optional peer of user-selected properties. | +| [ANNEAL-REQ-009](../settled-requirements.md#anneal-req-009-local-contract-obligations), [ANNEAL-REQ-010](../settled-requirements.md#anneal-req-010-local-results-compose-globally) | Property evidence must support local proof and global composition. | +| [ANNEAL-REQ-011](../settled-requirements.md#anneal-req-011-long-running-and-exceptional-behavior) | Verification cannot equate success with normal termination; it must express invariant-preserving divergence and sound panic, unwind, and recovery. | +| [ANNEAL-REQ-012](../settled-requirements.md#anneal-req-012-property-dependencies) | Property kinds may depend on one another, including through cycles that require a sound joint treatment. | +| [ANNEAL-REQ-013](../settled-requirements.md#anneal-req-013-property-selection) | Users must eventually be able to select which non-foundational properties are enforced. | +| [ANNEAL-REQ-014](../settled-requirements.md#anneal-req-014-type-invariants-support-arbitrary-property-kinds), [ANNEAL-REQ-015](../settled-requirements.md#anneal-req-015-trait-invariants-support-arbitrary-property-kinds), [decision 0004](../decisions/0004-invariants-support-all-property-kinds.md) | Both invariant forms must carry arbitrary property kinds. | + +Topic-specific implications: + +- Selecting or defining another property cannot substitute for the soundness + obligations needed to interpret its theorem as a claim about Rust. +- A common execution model may share evidence among properties, but no + requirement forces domains with different semantics into identical proof + judgments. +- The taxonomy, dependency algorithm, cycle treatment, and command/reporting + vocabulary all remain open. + +## Taxonomy remains open + +One proposal distinguishes: + +- semantic outcomes and effects, such as return, panic or unwind, abort, + divergence, undefined behavior, and model or tool failure; +- standard assurance policies, such as soundness, panic freedom, termination, + partial correctness, and total correctness; and +- extensible user property domains, such as functional, relational, trace, + protocol, quantitative, or probabilistic properties. + +This proposal has deliberately been neither accepted nor rejected. These terms +are useful for exploring the space, but must not be exposed as a stable API or +used to infer settled semantics. Among other issues, a property like deadlock +freedom may concern traces, progress, concurrency resources, and termination at +once; “panic freedom” may need to distinguish panic, abort, and unwind; and the +boundary between a policy and a user domain may not survive real examples. + +## Questions to resolve + +### What is first-class? + +- Which concepts, beyond soundness, should Anneal itself understand? +- Should panic, unwind, abort, nontermination, and ordinary return be modeled as + outcomes, effects, predicates over traces, or some combination? +- Which concepts need dedicated compiler extraction or proof machinery, and + which can be libraries defined over a smaller semantic core? +- Can one representation cover safety properties, liveness properties, + hyperproperties, probabilistic claims, and quantitative bounds without + pretending that their proof rules are identical? + +Initial V2 is expected to supply an extensible architecture rather than +complete support for deadlock freedom, hyperproperties, quantitative bounds, +or cryptographic reasoning. + +### How are execution paths combined? + +V1 split “progress” from conditional correctness. Experience suggests that the +split duplicated symbolic-execution work and fit poorly with Aeneas's WP +specifications and `step`/`step*` tactics. The current direction is to build on +Aeneas's combined machinery and share symbolic execution across obligations. +It remains open: + +- how path-specific obligations are attached to normal return, panic, unwind, + abort, and unbounded execution; +- whether different property kinds consume a common execution certificate or + require domain-specific proof judgments; +- how cleanup during unwinding is modeled well enough to establish soundness; + and +- how partial or total correctness is requested without making soundness + depend on termination. + +The Aeneas revision examined during this design discussion represented several +exceptional situations through a coarse failure channel. A bounds check, +arithmetic overflow, explicit panic, undefined operation, unsupported model +feature, and tool failure can have very different implications. Before relying +on this observation, recheck the Aeneas revision pinned by the current +toolchain. We still need to determine which cases it combines, which +distinctions survive LLBC lowering, and whether to refine the semantic result +type, attach metadata, or express the distinctions in WP predicates. This is an +investigation, not a claim about the correct Aeneas API. + +### How do dependencies compose? + +- How are dependencies between property kinds declared and discovered? +- Should selecting a property automatically select its transitive dependency + closure? +- If a dependency is excluded, does verification fail, succeed relative to an + audited assumption, or vary by command profile? +- How should mutually dependent properties be proven? Candidate approaches + include an explicit joint certificate for each strongly connected component, + inductive closure, and coinductive closure for appropriate liveness claims. +- How are dependencies represented through generic functions, trait bounds, + dynamic dispatch, and separately verified crates? + +These choices interact with the meaning of an incomplete proof and with trust +reporting; see [trust and incremental adoption](trust-and-incremental-adoption.md). + +### What does the user select and see? + +- Are property kinds named globally, scoped to crates, or identified by Lean + propositions or Rust declarations? +- Can projects define new kinds with reusable proof rules, or only attach + arbitrary propositions to built-in mechanisms? +- Does a command select desired top-level guarantees, obligations to check, or + both? +- How should output distinguish “not requested,” “proved,” “assumed,” “blocked + by unsupported semantics,” and “not applicable”? +- Which guarantees belong in machine-readable artifacts so downstream crates + can rely on them? + +## Evaluation criteria + +An acceptable design must: + +1. Make it impossible to interpret another selected property as a + substitute for soundness. +2. Give panic, divergence, and recovery faithful meanings rather than treating + them all as failed verification or silently discarding their paths. +3. Preserve compositional reasoning across functions and crates. +4. Avoid performing essentially the same symbolic execution independently for + every property where evidence can safely be shared. +5. Allow specialized proof systems where sharing would erase a domain's + semantics. +6. Produce an audit result whose dependencies and assumptions a user can + understand. +7. Be testable on realistic examples before the vocabulary becomes stable. + +## Useful experiments + +- A server loop that maintains an invariant forever without promising + termination. +- A destructor that runs during unwinding and whose unsafe operations must + remain sound. +- A function whose soundness depends on a callee's cryptographic or protocol + property. +- A lock abstraction with mutually dependent ownership and deadlock claims. +- One implementation checked for soundness, panic freedom, and a functional + result property using shared symbolic execution. + +Related questions include [Rust safety integration](rust-safety-integration.md), +[memory, resources, and effects](memory-resources-and-effects.md), and +[proof authoring](proof-authoring-and-user-experience.md). diff --git a/anneal/agent_docs/design/open-questions/rust-safety-integration.md b/anneal/agent_docs/design/open-questions/rust-safety-integration.md new file mode 100644 index 0000000000..5009d291c4 --- /dev/null +++ b/anneal/agent_docs/design/open-questions/rust-safety-integration.md @@ -0,0 +1,165 @@ + + +# Integration with Rust's safety machinery + +**Status:** Open design discussion. + +Rust has a familiar, compiler-enforced vocabulary for `unsafe fn`, `unsafe` +blocks, and unsafe traits. As of this page's 2026-07-17 review, unsafe fields +were under development upstream; that status is volatile and must be rechecked +before it becomes an implementation premise. Rust also has ecosystem +conventions and lints around `# Safety` documentation and `// SAFETY:` comments. +That machinery tracks only one undifferentiated notion of safety, while Anneal +must support multiple property kinds and stronger proof obligations. V2 must +decide where to extend Rust's system and where to create an Anneal-owned system +alongside it. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-001](../settled-requirements.md#anneal-req-001-v2-is-a-clean-room-redesign), [decision 0001](../decisions/0001-v2-is-a-clean-room-redesign.md) | V1 syntax and its mapping to Rust `unsafe` are evidence, not defaults. | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational) | Soundness remains mandatory under every integration strategy. | +| [ANNEAL-REQ-014](../settled-requirements.md#anneal-req-014-type-invariants-support-arbitrary-property-kinds), [ANNEAL-REQ-015](../settled-requirements.md#anneal-req-015-trait-invariants-support-arbitrary-property-kinds), [decision 0004](../decisions/0004-invariants-support-all-property-kinds.md) | Type and trait invariants are required and must support arbitrary property kinds. | +| [ANNEAL-REQ-016](../settled-requirements.md#anneal-req-016-contracts-distinguish-semantic-roles) | Rust's single safety axis cannot erase distinctions among Anneal obligation roles. | +| [ANNEAL-REQ-022](../settled-requirements.md#anneal-req-022-incremental-adoption-supports-prose), [decision 0005](../decisions/0005-incremental-adoption-supports-prose-justifications.md) | Selected formal obligations may be replaced temporarily by explicit, audited prose justifications. | +| [ANNEAL-REQ-026](../settled-requirements.md#anneal-req-026-upstream-evolution-is-in-scope) | Rust language and specification evolution is in long-term scope. | + +Topic-specific implications: + +- A safe Rust API must remain sound for every type-checked safe use, even when + its implementation uses unsafe code or Anneal tracks additional properties. +- Type invariants cannot be omitted because V1's mechanism was unsound, and V2 + need not wait for unsafe fields: Rust support and Anneal-specific analysis + are both candidates. +- Rust's existing unsafe boundaries offer familiar enforcement and migration + points, while arbitrary property kinds may require Anneal-owned scopes. The + balance between those systems remains the question being decided. + +## The central choice + +At one end of the design space, Anneal could map formal soundness obligations +closely onto Rust's existing unsafe boundaries. This would reuse compiler +checks, programmer expectations, documentation conventions, Clippy lints, and +incremental workflows. A Rust `unsafe` block could be the place where either a +formal proof or an audited prose justification discharges an obligation. + +At the other end, Anneal could maintain a richer parallel system. It could +track separately named property kinds, require proof around operations Rust +does not mark unsafe, and support type invariants before unsafe fields +stabilize. This avoids forcing concepts such as panic freedom or cryptographic +correctness into Rust's single `unsafe` bit. + +A hybrid is plausible: use Rust boundaries as authoritative evidence for some +soundness obligations while layering general property tracking and additional +invariant-sensitive operations on compiler-resolved program facts. The exact +division, reconciliation rules, and user vocabulary remain open. + +## Questions to resolve + +### Which Rust constructs carry Anneal meaning? + +- Does every `unsafe` operation generate an Anneal soundness obligation, or do + obligations attach only to unsafe leaves with modeled semantic guards? +- Is an `unsafe` block evidence of the intended proof scope, a syntactic place + to write a proof, or merely a Rust type-checking construct? +- How are unsafe functions whose callers provide prose `# Safety` contracts + related to machine-readable Anneal contracts? +- Can an operation be safe under Rust's soundness axis but guarded under another + Anneal property kind? If so, what source construct marks it? +- How should unsafe traits and future language features interact with Anneal's + trait invariants? + +Rust's `unsafe` syntax identifies responsibility boundaries; it does not by +itself fully state the semantic preconditions that make an operation sound. +Any design that reuses the syntax still needs an adequate specification of +those preconditions. See [source/model adequacy](source-model-adequacy.md). + +### How are property kinds spelled? + +A hypothetical Rust feature such as `unsafe(soundness)` or +`unsafe(panic_freedom)` illustrates the desired distinction, but does not exist. +V2 must decide whether annotations: + +- name property kinds independently of Rust syntax; +- decorate existing unsafe functions, blocks, traits, and fields; +- introduce Anneal-specific proof scopes for operations that Rust considers + safe; or +- combine these approaches and require exact reconciliation. + +The answer must work for user-defined kinds without requiring a Rust language +change for each new domain. It must also avoid implying that a caller may +violate the soundness of a safe Rust API merely because no Anneal property was +selected. + +### How are type invariants protected? + +V1's `isValid` concept demonstrated the usefulness of type invariants but did +not prevent safe code from mutating fields without re-establishing them. V2 +needs an enforcement boundary. Candidate mechanisms include: + +- Rust unsafe fields, once their exact semantics are usable; +- Anneal analysis that marks reads, writes, borrows, moves, construction, and + destruction of invariant-carrying representation as proof-requiring; +- module or constructor boundaries; +- explicit invariant-opening and invariant-closing operations; +- refinement wrappers whose representation cannot be accessed directly; and +- combinations of these for different kinds of invariant. + +The design must account for pattern matching, field projection, mutable and +shared borrowing, interior mutability, destructuring assignment, unions, +layout operations, drop, and code generated by macros. It must say when an +invariant may be temporarily broken, who owns the capability to restore it, +and how resource-sensitive facts are consumed. See +[contracts and invariants](contracts-and-invariants.md) and +[memory, resources, and effects](memory-resources-and-effects.md). + +### How does prose coexist with proofs? + +Some version of prose-based discharge is required for incremental adoption. +Open choices include: + +- whether an existing `// SAFETY:` comment is enough or must carry an explicit + Anneal marker; +- whether comments discharge individual call-site obligations, whole unsafe + blocks, or selected subtrees; +- which property kinds may use prose; +- whether prose uses an axiom-like or shared admission mechanism, a dedicated + status or provenance record, or another representation, while reports still + distinguish it from axiomatic semantics, incomplete proofs, and checked + evidence; +- whether Anneal checks that every Rust unsafe boundary has either proof or + prose, even when only part of a crate is formally adopted; and +- how later tooling helps replace prose with proofs without changing the Rust + code's structure. + +Prose can mark a trust gap; it cannot silently supply a machine-checked theorem. +The command and ledger semantics are discussed in +[trust and incremental adoption](trust-and-incremental-adoption.md). + +## Evaluation criteria + +Compare candidate integrations by asking: + +1. Does safe Rust retain its unconditional soundness promise? +2. Can the system express independent and dependent property kinds without + abusing Rust's single safety axis? +3. Can every invariant-sensitive operation be found in expanded, + compiler-resolved code, including generated code? +4. Is responsibility visible and familiar enough for Rust engineers to review? +5. Can a project adopt Anneal gradually without disguising trust gaps? +6. Does the design continue to work if Rust gains unsafe fields or richer + safety annotations? +7. Can the implementation fail closed when Rust and Anneal views disagree? + +Useful prototypes should include an invariant-carrying type before unsafe +fields, a crate mixing formal proofs and `// SAFETY:` comments, and a +property other than soundness attached to an operation Rust considers safe. The +compiler metadata needed for those experiments is covered in +[Aeneas and Charon integration](aeneas-charon-integration.md). diff --git a/anneal/agent_docs/design/open-questions/source-model-adequacy.md b/anneal/agent_docs/design/open-questions/source-model-adequacy.md new file mode 100644 index 0000000000..8e907826bd --- /dev/null +++ b/anneal/agent_docs/design/open-questions/source-model-adequacy.md @@ -0,0 +1,168 @@ + + +# Source/model adequacy + +**Status:** Open design discussion. + +Anneal's intended verification pipeline uses Aeneas and Lean to prove that +unsafe operations satisfy their preconditions, yet the correspondence between +Rust and the generated model is only promised for sound Rust programs. An +unsound Rust program may be lowered to a Lean definition that bears no useful +relationship to its source. V2 must close this apparent circularity rather +than merely assume that successful Lean proofs describe the original program. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-005](../settled-requirements.md#anneal-req-005-soundness-is-foundational), [ANNEAL-REQ-006](../settled-requirements.md#anneal-req-006-soundness-specifications-produce-adequate-obligations) | A source-level soundness result requires adequate, non-erasable obligations for all supported Rust safety conditions. | +| [ANNEAL-REQ-007](../settled-requirements.md#anneal-req-007-the-memory-model-is-conservative) | Trusted unsafe-leaf guards must conservatively reflect the normative Rust guarantees being claimed. | +| [ANNEAL-REQ-017](../settled-requirements.md#anneal-req-017-initial-claims-are-artifact-scoped), [decision 0002](../decisions/0002-verification-is-artifact-scoped.md) | The initial theorem concerns one fixed Cargo compilation artifact, not every build configuration. | +| [ANNEAL-REQ-018](../settled-requirements.md#anneal-req-018-generated-rust-is-analyzed-input), [decision 0003](../decisions/0003-expanded-generated-rust-is-input.md) | Expanded generated Rust ingested by Charon is analyzed input rather than trusted merely because a generator produced it. | +| [ANNEAL-REQ-019](../settled-requirements.md#anneal-req-019-coverage-adequacy-is-enforced) | Every potentially invalid source operation in the reported coverage envelope must receive the obligations needed to justify the proof model. | +| [ANNEAL-REQ-020](../settled-requirements.md#anneal-req-020-the-tcb-is-explicit-and-shrinkable), [ANNEAL-REQ-021](../settled-requirements.md#anneal-req-021-results-carry-an-audit-ledger), [decision 0006](../decisions/0006-the-tcb-is-explicit-and-shrinkable.md) | Unproved correspondence, toolchain, coverage, and primitive-semantic assumptions remain explicit and replaceable. | +| [ANNEAL-REQ-026](../settled-requirements.md#anneal-req-026-upstream-evolution-is-in-scope) | Rust, Charon, Aeneas, and Anneal may all change to support a defensible adequacy argument. | + +Topic-specific implications: + +- A Lean theorem about an inadequate or incompletely covered model is not a + theorem about the Rust artifact. Model and tool failures therefore cannot be + reported as successful source verification. +- Proposition-valued function arguments and sidecar call-site theorems are + alternative obligation encodings. Neither is sufficient without complete + coverage and a semantic argument connecting discharged guards to source + validity. +- The exact adequacy theorem, extraction point, coverage unit, and division + between proof and trusted translation remain open. + +## The required semantic connection + +We need a precise theorem connecting source executions, extracted semantics, +and generated proof obligations. Its exact statement is open. Candidate proof +families include: + +- an execution-prefix argument showing correspondence while validity + conditions hold and ruling out a first invalid operation by proving every + required guard; +- a forward or backward simulation maintained under an explicit source + validity invariant; and +- per-artifact translation validation that checks the extracted operations and + obligations against a separately justified semantic relation. + +These are sketches, may overlap, and are neither exhaustive nor accepted. Any +formulation must account for nondeterminism, concurrency, unwind and abort +behavior, infinite executions, provenance, external effects, compiler +transformations, and whatever relation Aeneas actually proves between LLBC and +Lean. + +The important distinction is between the semantic argument and the Lean API +used to present an obligation. Proposition-valued parameters make unguarded +model calls ill-typed; sidecar WP theorems may reuse Aeneas machinery more +directly. Either presentation still requires a theorem explaining why proving +the obligations rules out undefined source behavior. + +## Questions to resolve + +### Where is the authoritative program captured? + +- At which rustc phase must Charon extract the program so operations are still + present and their semantics have not already been changed by optimizations + that assume away undefined behavior? +- Are MIR and LLBC sufficiently expressive to identify every relevant unsafe + primitive and path, including drop glue, compiler-generated shims, intrinsics, + unwinding, and monomorphized calls? +- What compiler transformations occur before extraction, and what assumptions + do they make? +- Which source annotations survive expansion and lowering, and how are they + reconciled with compiler-resolved items? + +[Issue #3041](https://github.com/google/zerocopy/issues/3041) raises the risk +that extraction after UB-exploiting optimization could erase exactly the +operation Anneal needs to guard. This remains an investigation; V2 must not +assume the current extraction point is adequate without evidence. + +### What counts as complete coverage? + +- How are direct calls, trait dispatch, function pointers, closures, virtual + calls, recursion, drop glue, statics, and compiler intrinsics enumerated? +- Is proof coverage stated over syntactic call sites, semantic operations, + reachable monomorphized instances, or another unit? +- How are unreachable code and dead branches justified? +- What happens when Charon or Aeneas omits an unsupported construct? +- How does separate compilation carry verified contracts without assuming that + dependency code was built with different features or targets? +- How does Anneal prove that its annotation index and the LLBC artifact describe + the same items? + +Coverage should be machine-checkable and appear in the audit artifact where it +depends on assumptions. See +[Aeneas and Charon integration](aeneas-charon-integration.md) and +[trust and incremental adoption](trust-and-incremental-adoption.md). + +### What semantics do leaf guards express? + +Raw pointer dereference, pointer arithmetic, reads and writes, allocation, +deallocation, intrinsics, inline assembly, and FFI have different semantic +foundations. For each leaf V2 must determine: + +- the Rust operation being modeled; +- the precondition sufficient to rule out its undefined behaviors; +- the result and effects available to subsequent proofs; +- resource ownership or provenance consumed and produced; +- panic, unwind, abort, and divergence behavior where applicable; and +- which facts are proven, derived from Rust's specification, or trusted. + +An explicit set of assumptions is not automatically a conservative model of +normative Rust guarantees. The relationship must itself be documented and, +where possible, mechanized. Resource-bearing guards are discussed in +[memory, resources, and effects](memory-resources-and-effects.md). + +### What must be proved about the toolchain? + +- Is the adequacy theorem end-to-end, or a composition of rustc-to-LLBC, + LLBC-to-Lean, Anneal instrumentation, Lean kernel, and code-generation claims? +- Which translations are formally verified, validated per artifact, tested, or + trusted? +- Can Anneal independently validate that generated Lean contains all expected + obligations without brittle text rewriting? +- Which host compiler, LLVM, linker, and target hardware assumptions affect the + final claim rather than only tool availability? + +These questions do not require V2 to verify its entire toolchain immediately. +They do require an honest boundary and a path to shrink it. + +## Candidate approaches + +Candidate work can be combined: + +- extend Charon with compiler-resolved annotations and an operation index; +- validate LLBC against an independently generated obligation manifest; +- extend Aeneas's WP semantics with guarded unsafe leaves; +- make guards proposition-valued inputs to selected generated Lean functions; +- generate sidecar theorems and have Anneal verify one theorem per indexed + operation; +- prove an adequacy or trace-simulation theorem connecting complete guards to + source validity; and +- add fail-closed coverage checks for every unsupported or unmatched item. + +Textual patches to generated Lean are less desirable than programmatic +interfaces, but the criterion is robustness and semantic auditability, not a +categorical ban on any implementation technique. + +## Evaluation criteria + +A successful approach must state exactly which source artifact it covers, +identify every operation that can invalidate the source/model relationship, +make missing obligations detectable, preserve outcome and resource semantics, +and expose its trusted assumptions. It should also let V2 reuse Aeneas's WP +machinery rather than rebuilding it without need. + +The result should survive adversarial examples: an invalid operation optimized +away, an unsafe action in generated drop glue, a trait call resolved only after +monomorphization, and a panic path that runs unsafe cleanup. diff --git a/anneal/agent_docs/design/open-questions/trust-and-incremental-adoption.md b/anneal/agent_docs/design/open-questions/trust-and-incremental-adoption.md new file mode 100644 index 0000000000..efbc6d3ed4 --- /dev/null +++ b/anneal/agent_docs/design/open-questions/trust-and-incremental-adoption.md @@ -0,0 +1,163 @@ + + +# Trust and incremental adoption + +**Status:** Open design discussion. + +Anneal must be useful before an entire codebase has been modeled, while making +it impossible to confuse a partially trusted result with an end-to-end proof. +It must also support genuinely external semantics that may remain axiomatic for +the foreseeable future. V2 therefore needs first-class accounting for trust, +incompleteness, and adoption state. + +## Settled constraints + +| Authority | Constraint on this question | +| --- | --- | +| [ANNEAL-REQ-006](../settled-requirements.md#anneal-req-006-soundness-specifications-produce-adequate-obligations) | Non-axiomatic soundness specifications require machine-enforced adequacy rather than human intent alone. | +| [ANNEAL-REQ-017](../settled-requirements.md#anneal-req-017-initial-claims-are-artifact-scoped), [decision 0002](../decisions/0002-verification-is-artifact-scoped.md) | Trust and incompleteness qualify a result about one precisely identified compilation subject. | +| [ANNEAL-REQ-020](../settled-requirements.md#anneal-req-020-the-tcb-is-explicit-and-shrinkable), [decision 0006](../decisions/0006-the-tcb-is-explicit-and-shrinkable.md) | Trusted semantic leaves and the broader end-to-end TCB must be explicit and replaceable by deeper models. | +| [ANNEAL-REQ-021](../settled-requirements.md#anneal-req-021-results-carry-an-audit-ledger) | Every result must expose its exact claim, dependencies, trust, incompleteness, coverage, toolchain, environment, and hardware assumptions. | +| [ANNEAL-REQ-022](../settled-requirements.md#anneal-req-022-incremental-adoption-supports-prose), [decision 0005](../decisions/0005-incremental-adoption-supports-prose-justifications.md) | Selected obligations may temporarily rely on prose, but that reliance is an explicit residual dependency rather than a completed proof. | +| [ANNEAL-REQ-023](../settled-requirements.md#anneal-req-023-axioms-cover-genuine-external-semantics) | Fully adopted code should reserve axioms for genuine semantic boundaries; standard-library primitives and FFI remain important expected uses. | +| [ANNEAL-REQ-024](../settled-requirements.md#anneal-req-024-incompleteness-is-distinguishable-from-external-trust) | An intended but unfinished proof must remain distinguishable from an intentionally axiomatic specification. | + +Topic-specific implications: + +- A result containing residual dependencies must identify their kind, origin, + and affected claim. When a dependency has a known path to stronger evidence, + the ledger should expose it; a successful exit code cannot erase the + dependency. +- The meaning of a user-defined property comes from the user; any unproved + proposition assumed about it remains a residual dependency. Anneal enforces + and reports that assumption but cannot validate the intended meaning. This + differs from responsibility for the adequacy of primitive soundness guards. +- Command statuses, policy profiles, ledger schema, and authorship or + distribution of external specifications remain open. + +## Distinct evidence classifications and roles + +Not every residual dependency is trusted, and not all missing evidence means +the same thing. At minimum, the design must preserve distinctions among: + +- an axiom representing genuinely external semantics; +- a primitive-semantic assumption, with its actual origin and owner; +- a specification whose proof is intended but not complete; +- a call site temporarily justified by a prose `// SAFETY:` explanation; +- source or generated code intentionally outside the adoption scope; +- a construct modeled only through an opaque specification; +- an unsupported, skipped, or unmodeled construct; +- an admitted Lean theorem or equivalent escape hatch; +- a compiler, translator, kernel, runtime, or hardware assumption; and +- a model/tool failure that prevents any defensible claim. + +These may share implementation machinery, but users need to know each item's +status, role, owner, effect on the claim, and any known path to stronger +evidence. An approved semantic assumption may condition a claim; an incomplete +proof remains an unresolved proof obligation; a coverage or tool failure may +instead block the claim. The canonical definitions are in +[result and trust](../result-and-trust.md#what-trust-means). + +## Questions to resolve + +### What does command success mean? + +Candidate policies include: + +- `cargo anneal verify` fails on every incomplete proof but permits explicitly + approved axioms with a ledger; +- a separate incremental profile succeeds with a clearly conditional status; +- one command returns structured assurance grades and uses configurable exit + policy; or +- distinct commands separate end-to-end verification from partial checking. + +The design must avoid a state in which users or CI interpret “success” as a +stronger claim than the artifact supports. Open details include: + +- whether unrequested property kinds appear as gaps; +- whether a deliberately excluded dependency is an error or audited + assumption; +- how policy changes affect reproducibility; +- whether CI can impose a budget or allowlist for trust gaps; and +- what downstream crates may rely on from a partially verified dependency. + +### How are incomplete proofs represented? + +An explicit “specification present, proof incomplete” status may be preferable +to encoding incremental work as an axiom. It is analogous in purpose to Lean's +`sorry`, but V2 need not expose that mechanism directly. + +Questions include: + +- Is incompleteness attached to a theorem, obligation, source region, property + kind, or artifact? +- Does it preserve the intended specification for callers while marking its + proof as incomplete rather than established? +- Can a project prohibit new gaps while grandfathering existing ones? +- Does each gap have an owner, rationale, expiration, or issue link? +- How are transitive gaps summarized without losing their origin? +- Can a proof later replace the gap without changing the public verification + interface? + +### How do prose justifications work? + +Prose support is required, and a prose justification must remain +distinguishable from checked evidence. Its representation and binding semantics +are open: it could be a specialized admitted obligation associated with a Rust +unsafe boundary, a separate evidence status or provenance field, or another +form with Rust-oriented diagnostics. + +We need to decide: + +- which comments Anneal recognizes and how they bind to exact compiler-resolved + operations; +- whether prose is allowed only for soundness or for arbitrary property kinds; +- whether the text is included verbatim or hashed in the ledger; +- whether ordinary Rust linting conventions are reused; +- what happens when code moves and a comment no longer binds unambiguously; and +- how the tool guides conversion from prose to a machine proof. + +This intersects with [Rust safety integration](rust-safety-integration.md). + +### Who authors and distributes external specifications? + +For FFI and platform APIs, the specification might be authored by: + +- each Rust consumer; +- the C, C++, assembly, or platform library author; +- an Anneal standard-library or ecosystem package; or +- a third-party verification authority. + +V2 needs identities, versioning, target constraints, and a way to distinguish a +widely reviewed specification from a local assertion without turning social +trust into a misleading proof claim. Specifications may eventually be backed +by proofs in another system or by a formal ISA model. + +### What exactly is in the ledger? + +The canonical minimum inventory is defined in +[result and trust](../result-and-trust.md#audit-ledger). The remaining questions +concern representation and policy: exact field schema and granularity, stable +identities, normalization and reproducibility, serialization, signing, diff +format, retention and privacy, and the relationship between a machine-readable +artifact and a useful human audit view. + +## Evaluation criteria + +An acceptable design must be fail-closed about unsupported semantics, preserve +the difference between proof and trust, support useful incremental adoption, +and make transitive assumptions visible. It should reward shrinking the TCB, +allow external models to replace axioms, and produce stable artifacts suitable +for code review and CI policy. + +Useful experiments include a crate with one prose-justified call, a dependency +with an incomplete functional proof, an FFI binding with target-specific +axioms, and the same code verified under two compiler or hardware assumptions. +The source coverage needed to populate the ledger is discussed in +[source/model adequacy](source-model-adequacy.md). diff --git a/anneal/agent_docs/design/principles.md b/anneal/agent_docs/design/principles.md new file mode 100644 index 0000000000..b21f97b1a0 --- /dev/null +++ b/anneal/agent_docs/design/principles.md @@ -0,0 +1,144 @@ + + +# Design principles + +This page states Anneal's goals and the choice rules used when +[settled requirements](settled-requirements.md) and +[accepted decisions](decisions/README.md) do not determine an answer. Technical +mechanisms belong in the linked design documents; agent procedure belongs in +[`AGENTS.md`](../../AGENTS.md). + +## Goals and scope + +Anneal's long-term scope includes arbitrarily subtle correctness properties and +arbitrary Rust codebases. That scope guides the architecture; it does not +require the current executable or first milestone to support every Rust +construct or property domain. + +Unsafe Rust leaves soundness obligations which Rust's type system does not +discharge. Giving them rigorous, practical treatment is Anneal's foundational +use case, especially in unsafe-heavy systems code. Anneal must nevertheless +support functional correctness, protocols, panic freedom, resource bounds, and +other user-defined properties in the same framework. + +Anneal is intended for ordinary Rust organizations. Specialists and AI agents +may assist, but Rust engineers must be able to understand, debug, review, and +incrementally adopt the result. + +## Protect soundness and the meaning of every reported claim + +A theorem about modeled behavior supports the corresponding Rust claim only +insofar as the covered Rust behavior remains defined. Correspondence over an +execution prefix may help prove this condition, but soundness is still a +prerequisite for interpreting a model theorem as a fact about the Rust artifact. + +Anneal must account for every operation which can cause undefined behavior +under the supported Rust semantics and generate adequate obligations for it. A +weak, incomplete, or vacuous user specification cannot remove those +obligations. Unsupported semantics, missing coverage, and insufficient evidence +must narrow, condition, or prevent the reported claim instead of disappearing +behind a successful proof check. + +For a user-defined property, Anneal can enforce a precise definition but cannot +infer whether it captures the user's intent. A specification claiming +correspondence with Rust or another external semantics is different: its +adequacy is a claim-relevant dependency which must be justified or reported. +See the [verification model](verification-model.md) and +[result and trust](result-and-trust.md). + +## Prove abstraction boundaries once, then compose them + +An implementation becomes reusable through an abstraction boundary only after +it has been proved to satisfy the declared interface. That interface must +account for every claim-relevant interaction with the context, including +capabilities or resources exchanged across it. For soundness, a reusable safe +API must remain sound under every type-correct safe use admitted by that API +within the stated semantic and compilation envelope. + +Clients may then use the established guarantees without reopening the private +implementation. They may interact through declared mutation, allocation, I/O, +nondeterminism, or other effects, but neither side may impose undeclared +requirements on the other. This interface-relative isolation—not absence of +interaction—is the locality Anneal seeks. See +[contextual refinement](verification-model.md#contextual-refinement). + +## Introduce only the semantic machinery the claim requires + +A pure value-level contract is preferred when it fully describes the +abstraction boundary. Resource, provenance, initialization, ownership, +concurrency, protocol, or effect semantics are required whenever ignoring them +could invalidate the claim. + +For example, a freely reusable Lean fact cannot by itself authorize exclusive +mutation: two consumers could each cite it to justify access. Whether enforced +by a resource proposition, a state- or world-indexed weakest precondition, a +monadic discipline, or another mechanism, the proof interface must retain the +permission's usage rules. + +This yields a hybrid model without making “hybrid” a goal. The boundary between +functional translation and richer semantics evolves with Aeneas and Charon. +Revision-sensitive facts belong in the +[Aeneas and Charon reference](../reference/aeneas-and-charon.md); unresolved +architecture belongs in +[memory, resources, and effects](open-questions/memory-resources-and-effects.md). + +## Reuse general proof machinery after deriving the right Rust obligation + +Rust semantics determine the obligations. Once an obligation becomes a general +proof problem, Anneal favors proof abstractions maintained by Lean and +Aeneas—and compiler-resolved interfaces maintained by Charon—over parallel +special-purpose mechanisms. + +For example, `index < slice.len()` is one arithmetic sub-obligation among the +guards for `slice.get_unchecked(index)`. Aeneas's weakest-precondition +machinery and Lean's arithmetic support can derive that inequality from a +preceding bounds check; a separate Anneal bounds logic would duplicate rather +than improve the semantics. Other unsafe operations may additionally require +provenance, liveness, initialization, authority, or similar conditions which +need richer machinery; a concrete mismatch of that kind justifies extending +the underlying abstraction. + +This example does not decide how obligations are encoded. Interface and +upstreaming choices remain in the +[Aeneas and Charon integration discussion](open-questions/aeneas-charon-integration.md). + +## Expose and reduce every trusted dependency + +A dependency is trusted for a claim when the claim relies on its correctness +but the included checked evidence does not establish it at the claimed semantic +endpoint. Translation into Lean does not itself remove trust. + +Semantic assumptions, extraction and correspondence, tool correctness, +pipeline integration, and execution-platform assumptions play different roles +and must remain distinguishable. An incomplete proof is an unresolved +obligation, not an approved semantic boundary; coverage gaps and tool failures +may narrow or block a claim rather than become assumptions. + +Trusted dependencies must be visible and replaceable by stronger evidence. +Moving one into a helper or upstream component does not reduce trust unless the +end-to-end dependency is removed. Definitions, classifications, and audit +requirements live in [result and trust](result-and-trust.md). + +## Make partial adoption useful without calling it complete + +Anneal must support incremental adoption, including selected prose +`// SAFETY:` justifications and a distinct representation of unfinished +proofs. Neither may silently become checked evidence. Results must identify what +was checked, what remains, which claim the evidence supports, and what would +strengthen it. + +Among designs preserving those distinctions, this principle favors stable +proof interfaces, source-linked diagnostics, resilience to small changes, and +feedback useful to ordinary Rust engineers. + +## Relationship among the principles + +Soundness and claim integrity constrain acceptable designs. Among those +designs, simplicity, reuse, trust reduction, coverage, maintenance, and user +experience require case-specific judgment rather than a permanent total order. diff --git a/anneal/agent_docs/design/result-and-trust.md b/anneal/agent_docs/design/result-and-trust.md new file mode 100644 index 0000000000..5b62158340 --- /dev/null +++ b/anneal/agent_docs/design/result-and-trust.md @@ -0,0 +1,374 @@ + + +# Result and trust + +This document defines what identifies an Anneal result, which dimensions its +claim must state, how checked evidence differs from residual dependencies, and +what users must be able to audit. The +[verification model](verification-model.md) explains how local obligations +compose to produce the result. + +Anneal does not eliminate trust by translating Rust into Lean. It must instead +report exactly which claim its evidence supports and expose every dependency +needed to connect that evidence to the claim. The exact serialization, command +profiles, and exit-status policy remain open; see +[trust and incremental adoption](open-questions/trust-and-incremental-adoption.md). + +## What trust means + +A dependency is trusted for a reported claim when that claim relies on the +dependency's correctness but the result's included checked evidence does not +establish it at the claimed semantic endpoint. Trust is therefore relative to +a particular result and claim, not an intrinsic label on a component. A +compiler may be irrelevant to a theorem stated only about a Lean model but +essential to a claim about the binary it produces. + +Different trusted dependencies play different roles. A semantic assumption +says what an operation or environment means. Tool trust says that a component +handled its inputs and semantics correctly. Integration or correspondence +trust says that the components, identities, and artifacts are connected to the +same compilation subject correctly. Execution-substrate trust connects a Rust +or binary claim to the platform and hardware on which it runs. + +An incomplete proof and an unchecked admission have distinct statuses, but +neither includes checked evidence for the required argument. An incomplete +proof records unresolved proof work; an unchecked admission is an escape hatch. +Neither becomes an intentional semantic boundary merely because Lean can +represent both using axiom-like declarations. Likewise, a coverage gap or tool +failure may narrow or block a claim instead of becoming an assumption the claim +is permitted to rely on. **Residual dependency** is therefore broader than +**trusted dependency**. + +## Compilation-subject and result identity + +Anneal's initial subject is one concrete Cargo compilation artifact. Here, +“compilation artifact” means the compiler-resolved Rust program and semantic +configuration selected for verification, not the native executable, library +archive, or other file emitted by Cargo. “Compilation subject” is the preferred +phrase when that distinction matters. + +The compilation subject changes whenever an input can change the Rust program +presented to Charon or its source-level semantics. Rust emitted by procedural +macros or build machinery and then ingested by Charon is part of that subject. +It is analyzed like checked-in Rust rather than trusted merely because a +generator produced it. This does not make execution of the generator itself +part of the proved Rust program, nor does it verify every output that the +generator could produce. + +A verification result has a separate identity. It combines the compilation +subject with a precise claim, checked evidence, residual dependencies, and the +models and tools that produced or checked them. Changing a proof, property +selection, translator, semantics, or trusted specification can therefore +produce a different result about the same compilation subject. + +Classify an input by what it can change: + +- an input that changes the compiler-resolved Rust program or its source + semantics participates in compilation-subject identity; +- an input that changes extraction, modeling, obligations, evidence, selected + claim, or assumptions participates in verification-result identity; and +- an input that changes only the relationship between the Rust subject and a + binary execution qualifies that execution claim. + +One component may have several roles. A rustc revision, for example, can +change the compilation subject and also remain part of the end-to-end TCB. +Classify the actual dependency rather than permanently assigning each tool to +one bucket. + +Verification across targets, features, panic strategies, dependency versions, +or other build-matrix cells initially produces multiple subject-specific +results. Tooling may group and deduplicate them, but must identify which cells +were checked, omitted, or assumed. A prior result must not be silently +generalized to a related subject. + +## Claim dimensions + +“Verified” is incomplete unless the result states independent dimensions of +the claim: + +### Property and guarantee + +The result identifies each asserted property, the guarantee established for +it, and every dependency on another property or assumption. Rust soundness is +foundational; selecting another property does not silently remove the +soundness basis needed to interpret the model as Rust. + +### Behavior + +The result identifies which source behaviors the guarantee covers. Normal +return, panic and unwind, abort, and divergence can support different +obligations. A soundness result does not imply panic freedom or termination +unless those guarantees are also stated and proved. + +### Client and coverage envelope + +The result identifies the items, paths, call sites, generic instances, and +clients covered. Proving all concrete uses in one compilation subject is +different from proving contextual refinement for every type-correct safe use +admitted by an API within a stated envelope. Omitted or unsupported coverage +may not be inferred to have been checked. + +### Semantic endpoint + +The result identifies the semantic object about which it makes a claim. A +Lean-kernel theorem concerns declarations in a Lean environment. A claim about +the Rust compilation subject additionally depends on adequate extraction, +translation, obligation generation, and Rust semantics. A claim about a +compiled binary executing on target hardware additionally depends on the +compiler, linker, ABI, platform, and hardware connection. + +These endpoints and the other dimensions are not one linear hierarchy. A +result can strengthen its client quantification without extending to target +hardware, or add panic freedom without changing its semantic endpoint. Every +reported result must state the actual combination rather than present one +ambiguous assurance grade. + +### Conditions + +The claim is relative to every explicit semantic, environmental, and trusted +dependency that remains after proof checking. A condition can make a result +useful without making it unconditional. Its type and consequences must remain +visible. + +## Evidence and residual dependencies + +Every evidence-graph leaf, proof obligation, and coverage boundary needs enough +classification for users and tools to distinguish its evidence, its role in +the claim, and its coverage or modeling disposition. These dimensions are +independent even if the eventual report schema represents them differently. + +### Evidence classification + +The following distinctions must remain observable. They need not become +mutually exclusive values in one status enum: the eventual schema may use +statuses, subtypes, provenance fields, or several of these. + +- **Checked evidence:** Lean or another accepted checker established the + obligation relative to that checker's environment and assumptions. +- **Approved assumption:** an explicit premise is permitted to condition the + reported claim without evidence establishing it in this result. Its role, + origin, owner, and effect on the claim must be recorded. A specialized form, + such as a prose justification, retains that more specific provenance. +- **Incomplete proof:** a formal obligation is intentionally recorded as work + whose checked evidence has not yet been completed. +- **Unchecked admission or escape hatch:** an admitted theorem, unclassified + axiom, or equivalent bypass supplies no ordinary checked evidence. It must be + detected and reported separately from intentional incompleteness and approved + semantic boundaries. +- **Prose justification:** a human safety argument is relied upon for + incremental adoption in place of a machine-checked proof. Whether the schema + represents it as a specialized admission, a distinct status, or another form + remains open, but the result must preserve the distinction. +- **Tool or model failure:** verification could not establish the requested + result. This is not a source-program outcome and supplies no evidence that + the source property holds or fails. + +### Coverage and modeling disposition + +- **Body or path selected for analysis:** the named implementation body or path + participates in the evidence graph. Its operations still require supported + semantics and adequate obligations. +- **Specification-only or opaque body:** clients use a specification without + analyzing the implementation body at this endpoint. This can be a legitimate + trusted semantic leaf rather than a coverage gap; the specification still + needs its own evidence classification and role in the claim. +- **Outside the selected adoption or coverage scope:** a named item, path, or + generated input is deliberately excluded from the claimed envelope. +- **In scope but uncovered or unreconciled:** an item, path, call, or operation + belongs to the claimed envelope but is absent from or not connected to the + evidence graph despite having supported semantics. This is a coverage + adequacy failure, not an intentional scope boundary. +- **Semantics represented:** the checked model assigns semantics and generates + obligations for the operations relevant to the claim. Whether that + representation and those obligations are adequate is classified separately + as a claim-relevant dependency. +- **Unsupported or unmodeled:** a relevant construct or semantics is not + represented by the checked model. The result must identify the claim this + prevents, narrows, or conditions. + +Coverage and modeling are themselves distinct: selecting a body does not prove +that every operation in it is modeled. A result may therefore need more than +one of these classifications. + +### Role in the claim + +- **Program-proof obligation:** the result must establish a primitive guard, + callee precondition, invariant, contract guarantee, or property-dependency + edge for the analyzed program. Incompleteness, prose, or an admission changes + its evidence treatment, not this role. +- **Program-semantic dependency:** the result relies on the specified meaning + of a primitive Rust or standard-library operation, FFI, assembly, an ISA, a + platform interface, or another part of the modeled program. Its origin and + owner must be recorded. Anneal is responsible for the adequacy of + specifications it provides and for exposing the adequacy dependency of any + specification it imports. +- **User-property dependency:** a user-authored proposition is used without + proof. Merely defining the intended meaning of a user property is part of the + claim, not a residual dependency; assuming that the program satisfies it is. + Anneal cannot infer whether the definition captures the user's intent. +- **Correspondence or integration dependency:** the result relies on source + extraction, translation, obligation coverage, identity reconciliation, or + composition connecting the same compilation subject correctly across stages. +- **Tool-implementation dependency:** the result relies on Anneal, Charon, + Aeneas, Lean, rustc, LLVM, a linker, or another tool behaving correctly. +- **Execution-substrate dependency:** the result relies on an ABI, allocator, + operating system, firmware, external service, foreign library, hardware + behavior, or another condition not established by the program proof. + +The final names and machine representation are open. Their semantic +distinctions are not. In particular, an approved semantic assumption, an +unfinished proof, an unchecked admission, a prose argument, an opaque body, a +coverage gap, and a tool failure support different conclusions. One item can +carry classifications in several dimensions, and its role alone does not +determine whether it allows, conditions, narrows, or blocks a result. + +An undischarged obligation means that Anneal has not established the requested +claim. It is a useful diagnostic about missing evidence, not by itself a proof +that the Rust source violates the property. + +## Two trust boundaries + +Evidence classification and role do not replace the need to distinguish the +scope of a trust boundary. Anneal must distinguish: + +- the **trusted semantic leaf boundary**: program operations whose behavior or + soundness requirements are specified axiomatically instead of proved from a + deeper model; and +- the **end-to-end TCB**: every implementation and assumption needed to connect + checked evidence to the claimed Rust or target execution. + +The initial semantic leaf boundary may include raw-pointer operations, unsafe +standard-library functions, intrinsics, assembly, FFI, and platform operations +whose behavior is exposed through axiomatic specifications rather than derived +from a deeper implementation model. Anneal's standard library will likely use +the same axiom facility to specify some of these leaves. Anneal's authors are +responsible for the adequacy of Anneal-provided soundness specifications. + +The end-to-end TCB is much broader. Depending on the semantic endpoint, it can +include Anneal's obligation generation, Charon's extraction, Aeneas's +translation and semantics, Lean's kernel and proof environment, rustc, LLVM, +linking, the interpretation of Rust and target specifications, operating +systems or firmware, foreign libraries, and host and target hardware. + +A small program-semantic leaf boundary does not make this broader TCB small. +The audit ledger must make clear which boundary a change actually shrinks. + +## Audit ledger + +Every result must expose enough information to reproduce its subject, interpret +its claim, inspect its evidence, and audit its residual dependencies. At +minimum, the ledger records: + +### Claim and scope + +- the property guarantees asserted and their dependencies; +- covered behaviors and exceptional outcomes; +- the client, item, path, call-site, generic-instance, and other coverage + boundaries; and +- the semantic endpoint and every condition needed to reach it. + +### Evidence and gaps + +- each obligation and dependency, with its evidence classification, role, and + any applicable coverage or modeling disposition; +- every trusted semantic leaf and axiom, including origin, owner, and affected + properties; +- every incomplete or admitted proof and every prose justification, with a + source location where applicable; +- every specification-only or opaque body, with the corresponding + specification and evidence classification; +- every skipped, unsupported, or unmodeled item or operation; +- coverage gaps and the claims they prevent or condition; and +- dependencies among proofs, properties, specifications, and assumptions. + +### Compilation subject + +- workspace, package, Cargo target, target kind, profile, source revision or + other source identity; +- dependency resolution and enabled features; +- target triple or specification, `cfg` values, panic strategy, overflow + behavior, and other source-semantics-relevant compiler options; +- generated Rust, proc-macro expansion, build outputs, and included files that + form the compiler-resolved subject; and +- relevant environment variables, build-script directives, ABI, and other + inputs or assumptions affecting that subject. + +### Verification evidence and toolchain + +- Anneal, Aeneas, and Charon versions or revisions, options, models, + obligations, and downstream semantic patches; +- rustc, the Rust standard library, LLVM, linking tools, and relevant compiler + options; +- the LLBC, Lean declarations, checked proof artifacts, Lean, Lake, Mathlib, + and other proof-library versions needed to identify or reproduce the + evidence; and +- proof, extraction, translation, and reporting configuration not already + captured by the compilation subject. + +### Execution substrate + +- operating-system, firmware, external-service, foreign-library, and platform + assumptions relevant to the claim; +- the host hardware or trusted execution environment on which verification ran + to the degree needed to reproduce or assess the result; and +- the target hardware model or concrete implementation assumed by any binary + execution claim. + +If a result stops at a model or Rust-subject claim, the ledger states that +binary and target-hardware execution are outside the claim rather than implying +they were verified. Host hardware running the checker may nevertheless remain +in the practical TCB. + +Recording a field does not necessarily make it part of a future canonical +content identifier. Defining normalization, semantic equivalence, provenance, +signatures, storage formats, and the useful granularity of hardware identity +remains open. The ledger may not omit a claim-relevant dependency merely +because its canonical encoding is unsettled. + +## Fail-closed reporting + +“Fail closed” means Anneal must never silently report a claim stronger than its +evidence supports. It does not predetermine one command name or exit-code +policy. + +An approved external axiom may be compatible with a successful result whose +claim is explicitly relative to that axiom. An explicitly named incremental +mode may report a weaker conditional result with incomplete proofs or prose +justifications. Whatever policy is chosen: + +- every successful exit has a documented meaning; +- conditional or incomplete evidence is not labeled as an unconditional + verification result; +- omitted coverage remains visible and qualifies the claim; +- property dependencies cannot be disabled without being discharged or + reported as conditions; +- model and tool failures are not treated as source behaviors; and +- users can compare results and ledgers as evidence or trust changes. + +The distinction between a strictly verified mode and conditionally checked +profiles remains open. Anneal must settle that user-facing policy explicitly +rather than allowing implementation accidents to define it. + +## Reducing trust over time + +Stable abstraction contracts should be separable from the current depth of +their implementation model. This permits, for example: + +- a primitive-operation axiom to be replaced by a proved Rust operational + model; +- an assembly axiom to be replaced by an ISA-level proof; +- an FFI specification to be connected to a verified foreign implementation; +- a compiler assumption to be replaced by translation validation or verified + compilation; or +- a hardware assumption to be connected to a formal hardware model. + +The replacement reduces trust only if it supports the same or a stronger +end-to-end claim and removes the old dependency from the ledger. Moving an +assumption into generated code, a helper whose body is not modeled, or another +project without proving it does not shrink the TCB. diff --git a/anneal/agent_docs/design/settled-requirements.md b/anneal/agent_docs/design/settled-requirements.md new file mode 100644 index 0000000000..f09e9edc1c --- /dev/null +++ b/anneal/agent_docs/design/settled-requirements.md @@ -0,0 +1,274 @@ + + +# Settled requirements + +These requirements record constraints that have been unambiguously accepted +for Anneal V2. They deliberately avoid choosing among implementations still +under discussion. Stable identifiers allow code, decisions, and open questions +to refer to the requirement they serve. They are an atomic registry, not a +second explanation of the design philosophy: use the +[design principles](principles.md) to understand why these constraints matter +and the linked design documents for their canonical elaboration. + +## Project scope + +### ANNEAL-REQ-001: V2 is a clean-room redesign + +V2 must be designed from its goals and current evidence rather than inheriting +V1 by default. V1 code and ideas may be reused deliberately. Their existence is +not evidence that V2 should preserve them. + +See [decision 0001](decisions/0001-v2-is-a-clean-room-redesign.md). + +### ANNEAL-REQ-002: General properties + +The long-term architecture must support arbitrarily complex, user-defined +correctness properties. It must not encode an assumption that soundness is the +only property worth verifying. + +### ANNEAL-REQ-003: General Rust use cases + +The long-term architecture must be capable of covering arbitrary Rust +codebases and use cases. Initial milestones may support a strict subset, but +the architecture must not require unsafe-heavy domains to abandon their +essential memory, concurrency, or external-effect semantics. + +### ANNEAL-REQ-004: Extensibility before breadth + +Initial V2 need not ship specialized backends for deadlock freedom, +hyperproperties, cryptographic correctness, quantitative bounds, +probabilistic properties, or every other anticipated domain. It must leave a +path to add such domains without redesigning the core composition model. + +## Soundness and semantic fidelity + +### ANNEAL-REQ-005: Soundness is foundational + +Anneal must treat Rust soundness as a non-optional foundation of a faithful +verification result. Selecting another property kind must not silently disable +the soundness assumptions on which source-to-model correspondence depends. + +### ANNEAL-REQ-006: Soundness specifications produce adequate obligations + +For every non-axiomatic source of Rust soundness requirements, Anneal must +derive obligations sufficient for the supported semantics. In particular, the +specification of a primitive operation must impose the actual conditions +needed for its sound use. A weak, incomplete, or vacuous user contract must not +be able to erase those conditions. + +This is **obligation adequacy**: it concerns whether the generated obligation +is the right one. The separate coverage requirement +[ANNEAL-REQ-019](#anneal-req-019-coverage-adequacy-is-enforced) concerns +whether every relevant operation actually receives and discharges such an +obligation. How Anneal establishes either property is open; see +[source/model adequacy](open-questions/source-model-adequacy.md). + +### ANNEAL-REQ-007: The memory model is conservative + +Any Anneal-owned abstraction of Rust memory and unsafe operations must be a +conservative formalization of the normative guarantees Anneal claims to +support, not merely an undocumented set of convenient assumptions. Ambiguous +prose in Rust's specifications must be surfaced, resolved with the relevant +Rust teams where possible, and recorded as an assumption until resolved. + +### ANNEAL-REQ-008: Resource semantics are preserved + +Lifting separation-logic assertions, ownership, provenance, initialization, or +protocol state into Lean must preserve their usage discipline. Such resources +must not become freely reusable ordinary facts when that would invalidate the +reported claim. In particular, simplifying their use may not compromise +soundness. + +## Local and global verification + +### ANNEAL-REQ-009: Local contract obligations + +Locally, verification must establish that an item's preconditions imply its +applicable guarantees and that every invocation satisfies the required +preconditions or properties of its callees. + +The exact treatment of normal return, panic, unwind, abort, and divergence is +open; this requirement does not imply that every verified item terminates +normally. + +### ANNEAL-REQ-010: Local results compose globally + +Local obligations must compose into a whole-artifact guarantee relative to an +explicit set of trusted leaves and environmental assumptions. A caller must not +need to re-verify the private body of a callee whose contract has been +established. + +### ANNEAL-REQ-011: Long-running and exceptional behavior + +The verification model must be able to express and justify: + +- a server that executes without bound while preserving invariants; +- code that remains sound while panicking; +- unwind cleanup relevant to soundness; and +- code that catches a panic and continues execution. + +Anneal must not equate successful verification with normal termination in all +cases. + +### ANNEAL-REQ-012: Property dependencies + +Property kinds may depend on one another. All supported properties ultimately +depend on soundness, and a soundness obligation may itself rely on a declared +guarantee of another property kind. For example, a callee's functional +guarantee that an index is in bounds may discharge a caller's raw-pointer +soundness obligation. The architecture must not isolate each property kind in +a universe that cannot express these dependencies. + +“Ultimately depend on soundness” describes the semantic basis needed to +interpret model theorems as claims about Rust; it does not impose an acyclic +proof order in which soundness is always established first. Mutually dependent +obligations must be discharged jointly or by another sound treatment of +cycles. The representation and proof mechanism remain open. + +### ANNEAL-REQ-013: Property selection + +Users must eventually be able to choose which non-foundational property kinds +are enforced by a `cargo anneal verify` invocation. Dependency closure, +reporting, command modes, and handling of excluded dependencies remain open. + +## Contracts and invariants + +### ANNEAL-REQ-014: Type invariants support arbitrary property kinds + +V2 must support invariants associated with types, and those invariants must not +be limited to soundness. The V1 `isValid` mechanism is not an acceptable +implementation because safe field mutation could bypass invariant +re-establishment. + +V2 may build on Rust unsafe fields, perform its own field-access and mutation +analysis, or use another sound mechanism. It need not wait for unsafe fields to +stabilize. + +### ANNEAL-REQ-015: Trait invariants support arbitrary property kinds + +V2 must support invariants associated with traits for arbitrary property +kinds. It must enforce the invariant at the implementation site and make the +established invariant available where the corresponding trait bound is known. + +The V1 spelling `isSafe` is not a commitment to syntax or to a soundness-only +meaning. + +### ANNEAL-REQ-016: Contracts distinguish semantic roles + +The architecture must be capable of distinguishing a caller obligation needed +for Rust soundness from an ordinary functional-domain precondition and from +obligations of other property kinds. Rust's single `unsafe` axis does not erase +these semantic differences, even if V2 initially maps several of them onto +existing Rust syntax. + +## Artifact and translation boundary + +### ANNEAL-REQ-017: Initial claims are artifact-scoped + +The initial unit of verification is one Cargo compilation artifact with fixed +target, features, `cfg` values, dependencies, panic strategy, generated code, +and relevant environment. A claim across a build matrix requires multiple +artifact claims or future quantified support. + +See [decision 0002](decisions/0002-verification-is-artifact-scoped.md). +The subject and result identities are elaborated in +[result and trust](result-and-trust.md). + +### ANNEAL-REQ-018: Generated Rust is analyzed input + +Rust code produced by proc macros and build machinery and subsequently ingested +by Charon must be treated as part of the artifact being analyzed, rather than +trusted merely because a generator produced it. This does not by itself settle +how to model every non-Rust effect of a build script. + +See [decision 0003](decisions/0003-expanded-generated-rust-is-input.md). + +### ANNEAL-REQ-019: Coverage adequacy is enforced + +Anneal must ensure that every potentially invalid source operation in the +reported coverage envelope is guarded by the obligations needed to justify +the model used for its proof. An operation, path, or relevant generated item +must not disappear from coverage merely because the obligation generator, +translator, or proof interface failed to represent it. + +This is **coverage adequacy**: it concerns complete application of obligations +whose semantic content is governed by +[ANNEAL-REQ-006](#anneal-req-006-soundness-specifications-produce-adequate-obligations). +The encoding and enforcement mechanism remain open; see +[source/model adequacy](open-questions/source-model-adequacy.md). + +## Trust and adoption + +### ANNEAL-REQ-020: The TCB is explicit and shrinkable + +V2 may rely on a small set of trusted leaves, but they must be explicit, +auditable, and replaceable by deeper models over time. Near-term examples may +include unsafe standard-library leaves, intrinsics, raw-pointer operations, +FFI, and assembly. + +See [decision 0006](decisions/0006-the-tcb-is-explicit-and-shrinkable.md). +The program-semantic leaf boundary and the broader end-to-end TCB are +distinguished in [result and trust](result-and-trust.md). + +### ANNEAL-REQ-021: Results carry an audit ledger + +Users must be able to determine what remains trusted or incomplete. The ledger +must identify the exact subject and claim, checked evidence, residual +dependencies, coverage limits, relevant toolchain, and host and target +assumptions. The canonical minimum inventory is maintained in +[result and trust](result-and-trust.md#audit-ledger); the exact schema and +presentation remain open. + +### ANNEAL-REQ-022: Incremental adoption supports prose + +Some form of existing prose safety justification must be able to stand in for +selected Anneal proofs during incremental adoption. Such a justification is +not a machine-checked proof and must be identifiable in the audit ledger. + +See [decision 0005](decisions/0005-incremental-adoption-supports-prose-justifications.md). +Its evidence classification is defined in +[result and trust](result-and-trust.md#evidence-and-residual-dependencies). + +### ANNEAL-REQ-023: Axioms cover genuine external semantics + +In a fully adopted codebase, axioms should be reserved for genuine semantic +boundaries. Anneal's own standard library will likely use the same facility to +specify primitive unsafe operations, and FFI will likely require user- or +library-authored axioms for the foreseeable future. Who should author and +distribute FFI specifications remains open. + +### ANNEAL-REQ-024: Incompleteness is distinguishable from external trust + +The design must be able to report a proof that is not yet completed separately +from a specification intentionally taken as axiomatic. It is open whether this +uses a first-class incomplete-proof mechanism, command profiles, Lean `sorry`, +or another representation. + +## Ecosystem and usability + +### ANNEAL-REQ-025: Existing proof machinery is preferred + +V2 should build on suitable abstractions maintained by Lean, Aeneas, and their +standard libraries, including WP specifications and tactics, unless a concrete +benefit justifies replacement. This is a strong engineering preference rather +than a prohibition on new machinery. + +### ANNEAL-REQ-026: Upstream evolution is in scope + +Changes or additions to Aeneas and Charon are in scope. In the longer term, +Rust language and specification changes are also in scope. Short-term +implementation constraints must not be documented as permanent project +philosophy. + +### ANNEAL-REQ-027: Ordinary Rust engineers are a target audience + +The eventual workflow must be usable in normal Rust organizations, including +by engineers without formal-methods specialization. Human and AI assistance, +diagnostics, stable proof interfaces, and gradual adoption may all contribute; +none may weaken the meaning or auditability of a successful result. diff --git a/anneal/agent_docs/design/verification-model.md b/anneal/agent_docs/design/verification-model.md new file mode 100644 index 0000000000..44bfdffb5a --- /dev/null +++ b/anneal/agent_docs/design/verification-model.md @@ -0,0 +1,239 @@ + + +# Verification model + +This document describes how Anneal derives a verification result. It does not +choose an annotation syntax, outcome taxonomy, Lean encoding, command mode, or +report format. Subject and result identity, evidence classifications, trust +boundaries, and the canonical audit-ledger contents are defined in +[result and trust](result-and-trust.md). + +The high-level derivation is: + +```text +identified Rust subject ++ requested claim dimensions ++ evaluated evidence graph with classified leaves += reported result stating the established claim and remaining gaps +``` + +Each term matters. Evidence about an unidentified program is not reproducible. +A theorem without a precise requested claim invites overinterpretation. Local +proofs without an evaluated evidence graph do not establish a global result. +Each leaf must be classified as checked evidence, an admissible assumption, a +coverage limit, or a blocking gap or failure; otherwise an axiom, omitted +operation, or unfinished proof disappears into hidden trust. The reported +result states which claim was actually established, any explicit conditions +on it, and why each residual dependency remains. + +The [worked byte-buffer example](worked-example.md) illustrates this model +without ratifying a concrete proof architecture. + +## Subject and claim + +Anneal initially verifies one concrete Cargo compilation subject. Generated +Rust ingested by Charon is part of that subject rather than trusted because a +proc macro or build process produced it. The exact target, features, `cfg` +values, dependencies, panic strategy, generated inputs, and relevant +environment delimit the program to which the result applies. + +A claim about that subject has several independent dimensions: + +- the properties and guarantees asserted, including their dependencies; +- the source behaviors to which those guarantees apply, such as normal return, + panic and unwind, abort, or divergence; +- the client and coverage envelope, from concrete calls in one artifact to + every type-correct safe use admitted by an API within a stated envelope; and +- the semantic endpoint, from a theorem about a Lean model through a claim + about the Rust artifact to execution of a compiled binary on target + hardware; and +- the explicit conditions on which the claim depends. + +These dimensions must not be collapsed into one ladder of “verification +levels.” A source-level soundness result need not establish panic freedom. A +whole-artifact proof of concrete calls need not justify every separately +compiled client. A theorem checked by Lean need not establish a hardware +execution claim without the correspondence and toolchain dependencies needed +to connect them. + +The reporting definition and identity of each dimension are maintained in +[result and trust](result-and-trust.md#claim-dimensions). This document +describes the proof structure from which they are derived. + +## Local obligations + +For an item `f` and a selected property `P`, the schematic local claim is: + +1. assume `f`'s applicable preconditions, invariants, capabilities, + environmental conditions, and already established interface guarantees; +2. show that every call and primitive operation made by `f` satisfies the + required preconditions and property dependencies of the invoked operation; + and +3. show that every behavior covered by the claim establishes the applicable + guarantee of `f`'s contract. + +For a normal-return functional contract, this specializes to the familiar +statement that preconditions imply postconditions. It does not imply that all +claims require normal termination. A soundness claim may permit divergence or +a safe panic while requiring every executed prefix and relevant unwind cleanup +to remain sound. + +The same shape applies when an interface carries resources or effects, but its +assumptions and guarantees are not necessarily freely reusable propositions. +Ownership, provenance, initialization, permissions, protocol state, or an +opened invariant may need to be consumed, transferred, framed, or +re-established. The local proof interface must retain those rules. Treating a +resource as an ordinary duplicable Lean fact would change the claim rather than +simplify its proof. + +Type and trait invariants participate in these local interfaces. A type +invariant must be established and preserved at every relevant operation; a +trait invariant must be established by an implementation and made available +where its trait bound is known. Their concrete enforcement and syntax remain +open in [contracts and invariants](open-questions/contracts-and-invariants.md). + +## Global closure + +Local results form an evidence graph: + +- nodes establish item contracts, invariants, primitive specifications, or + deeper semantic facts; +- call edges require callers to establish callees' preconditions; +- property-dependency edges allow one guarantee to discharge an obligation of + another property; and +- leaf edges end either in checked evidence or in an explicitly classified + residual dependency. + +For example, a callee's functional guarantee that an index is below a buffer +length may discharge the soundness precondition of a caller's raw-pointer +access. This does not make soundness optional; the functional theorem is an +edge in the proof that the pointer access remains sound. + +An artifact-level claim follows only when every relevant non-leaf node +satisfies its local contract, every required edge is discharged, coverage is +adequate, and each remaining assumption is admissible for and included in the +conditions of that claim. Mutually dependent properties may require joint +reasoning; the graph model does not impose an artificial proof order in which +every soundness theorem must be completed before any other property can +contribute to it. + +For Rust soundness, the conditions assigned to primitive unsafe leaves must be +adequate. Anneal is responsible for conditions it provides and must report the +adequacy dependency of any specification it imports. If the conditions are +sufficient for the supported Rust semantics and every use establishes them, +the local results compose into an artifact-level soundness claim relative to +the recorded semantic and environmental dependencies. + +Classification alone does not discharge a residual dependency. Its status +determines whether Anneal can establish the requested claim relative to an +admissible assumption, must narrow or condition the claim, or cannot establish +a substantive claim at all. A tool failure supplies no evidence, and some +coverage gaps prevent rather than merely qualify a claim. Command policy may +decide which established conditional results count as success; it may not turn +a missing evidentiary connection into an assumption. See [evidence and residual +dependencies](result-and-trust.md#evidence-and-residual-dependencies). + +## Adequacy closes the source/model loop + +Anneal intends to use a model that is promised to correspond to sound Rust in +order to prove that the Rust subject is sound. It cannot resolve this apparent +cycle by assuming soundness unchecked. + +A source-level soundness result therefore needs both complete, adequate guards +for potentially invalid source operations and a justified correspondence from +the guarded source execution to the proof model. It must not assume the very +whole-program soundness that the guards are intended to establish. The exact +correspondence theorem and proof decomposition remain open. + +One candidate is a guarded-prefix argument: establish correspondence before a +first invalid source operation, identify and guard every operation that could +be that first invalid operation, and use checked evidence for those guards to +rule such an operation out. A trace simulation, translation validation, or +another construction may establish the same required connection instead. See +[source/model adequacy](open-questions/source-model-adequacy.md). + +Whichever proof family is chosen, two different adequacy requirements are +involved: + +- **Obligation adequacy** means that each generated guard expresses the right + Rust validity conditions. Primitive semantics and other non-axiomatic + sources of Rust requirements must determine those conditions; a user + contract cannot weaken them away (ANNEAL-REQ-006 in the + [settled requirements](settled-requirements.md)). +- **Coverage adequacy** means that every potentially invalid operation in + scope actually receives such a guard and that missing operations, paths, or + generated items prevent an unconditional result + ([ANNEAL-REQ-019](settled-requirements.md#anneal-req-019-coverage-adequacy-is-enforced)). + +How the guards and correspondence evidence are encoded, proved, and divided +among rustc, Charon, Aeneas, and Anneal remains open. The semantic requirements +do not choose between Lean proof arguments, sidecar theorems, or another +enforcement mechanism. + +Specification adequacy differs for a property whose meaning is supplied by the +user. Anneal can check that the declared definition is propagated and +enforced, but cannot infer whether it expresses the user's intended business, +cryptographic, or protocol requirement. If a specification claims +correspondence with Rust, an FFI implementation, an ISA, or another external +semantics, its adequacy remains an explicit trust dependency. + +## Contextual refinement + +Whole-artifact composition and reusable abstraction verification make +different claims. + +A whole-artifact result may cover only the concrete call sites, generic +instances, and reachable behaviors in one compilation subject. This is useful, +but it does not by itself prove a library safe for every future downstream +client. + +A reusable safe-API soundness claim requires robust safety: the implementation +must remain sound under every type-correct safe use admitted by the API within +a stated semantic and compilation envelope. More generally, contextual +refinement requires every implementation behavior visible to a context in the +quantified envelope to be permitted by the declared interface. Clients in that +envelope may then rely on the interface without reopening the private +implementation. Rust's underlying requirement is broad—an API presented as +safe must be sound for every type-correct safe use—even when Anneal can +initially report only a narrower artifact result. + +Every interaction relevant to the claim must be mediated by the interface and +by the capabilities or resources transferred across it. The implementation may +not silently invalidate context-owned resources or impose caller obligations +which the interface does not declare. This is not literal absence of +interaction, and the relevant boundary need not be a lexical scope. Allocators, +I/O, atomics, locks, nondeterminism, and other domains may expose deliberate +effects through effectful or resource-aware interfaces. + +The abstraction boundary may still be a pure value-level contract when that is +faithful. Contextual refinement requires it to preserve every observation and +discipline relevant to the claim; it does not require all unsafe +implementations to masquerade as pure functions. + +How Anneal exports and checks quantified contracts across separate compilation +remains open. Until it can establish that stronger claim, it must report the +narrower client envelope rather than silently generalize one artifact's +evidence. + +## Behavior remains part of the claim + +Anneal must support programs that return, panic safely, unwind through +soundness-relevant cleanup, catch a panic and continue, or execute indefinitely +while preserving invariants on every finite prefix. Verification therefore +cannot always mean normal termination. + +The proof model must distinguish enough source behavior to justify the +selected claim. It does not yet decide whether soundness, panic freedom, +termination, and other distinctions are built-in property kinds, standard +policies, effects in a weakest-precondition model, or user-defined predicates. +See [property kinds and outcomes](open-questions/property-kinds-and-outcomes.md). + +A model or tool failure is not a source-program behavior. It may create an +unsupported or incomplete result, but may never be interpreted as evidence +that the source satisfies a property. diff --git a/anneal/agent_docs/design/worked-example.md b/anneal/agent_docs/design/worked-example.md new file mode 100644 index 0000000000..0be3657f36 --- /dev/null +++ b/anneal/agent_docs/design/worked-example.md @@ -0,0 +1,226 @@ + + +# Worked example: an unsafe-backed byte buffer + +This schematic example connects the concepts in the +[verification model](verification-model.md) and +[result and trust model](result-and-trust.md). It is a teaching example, not a +normative design: `ByteBuffer`, the primitive leaves, predicates, proof +decomposition, outcome names, and result presentation below are all +illustrative. Names such as `BufferInvariant`, `owns`, and +`AbstractSequence` are explanatory notation rather than proposed Anneal or Lean +syntax. Open choices remain governed by the +[open-question ledger](open-questions/README.md). + +## The example abstraction + +Imagine a crate with this safe interface: + +```rust +pub struct ByteBuffer { /* private raw-pointer representation */ } + +impl ByteBuffer { + pub fn replace(&mut self, index: usize, value: u8) -> u8; +} +``` + +Internally, `ByteBuffer` owns a heap allocation and records a raw pointer, +length, and capacity. A schematic implementation of `replace` is: + +1. if `index >= len`, panic before touching the raw allocation; +2. otherwise call an unsafe primitive that replaces the byte at + `ptr + index` and returns the previous byte; and +3. return the previous byte. + +This resembles an implementation using `ptr::replace`, but the example does +not assert that `ptr::replace` should be Anneal's actual semantic leaf. + +## The trusted primitive leaf + +Suppose the Anneal standard library currently treats a primitive operation +called `replace_byte` as a trusted leaf. Its safety guard requires that: + +- the pointer identifies a live allocation with suitable provenance; +- the selected address is in bounds and properly aligned; +- the selected byte is initialized; and +- the caller holds exclusive authority to write that byte. + +The leaf's illustrative resource transition is: + +```text +owns(allocation, bytes) * index < length(bytes) + -- replace_byte(index, value) --> +owns(allocation, bytes[index := value]) * old = bytes[index] +``` + +Here `*` is only mnemonic notation for resource composition. Crucially, +`owns(allocation, bytes)` is consumed and replaced by the operation. It is not +an ordinary hypothesis that a proof may duplicate and use for two writes. The +exact resource logic or monadic machinery needed to enforce this discipline is +an [open design question](open-questions/memory-resources-and-effects.md). + +The primitive specification is trusted only at this boundary. Anneal must +still generate and check the guard at each call, and the ledger must identify +the specification as trusted. A future lower-level memory model could prove +the same leaf contract and remove that trust without changing `ByteBuffer`'s +public contract. + +## The type invariant + +For an abstract byte sequence `xs`, imagine an internal invariant with two +components: + +```text +BufferInvariant(buffer, xs) := + there is one live allocation described by buffer.ptr/len/capacity + * buffer has the exclusive owns(allocation, bytes) capability + * buffer.len = length(xs) + * the initialized prefix of bytes equals xs +``` + +The ownership component is soundness-relevant and resource-bearing. The +sequence relation supports an illustrative user-defined property, +`AbstractSequence`. A final design might represent those components together +or separately; this example does not decide that question. + +Holding a mutable reference to a valid `ByteBuffer` allows its implementation +to open the invariant according to controlled rules. It does not give arbitrary +proof code two copies of `owns`. Before control leaves the method normally or +by unwinding through relevant cleanup, the invariant must be available in the +state required at that boundary. + +Constructors must establish the invariant. Mutating methods must transform and +restore it. Destruction must consume the allocation capability exactly once. +Checking only `replace` while leaving construction, other field mutation, or +destruction unguarded would not establish the abstraction's soundness. + +## Contracts at the safe boundary + +The safe method has **no caller obligation whose violation permits undefined +behavior**. Every type-correct safe caller may pass any `usize`. In particular, +`index < len` is not a Rust safety precondition of `replace`. + +The API can nevertheless have ordinary outcome and functional contracts. One +illustrative contract says: + +- if `index` is out of bounds, the method panics without changing the abstract + sequence; +- if the method returns normally, the return value is the old byte at + `index`, and the new abstract sequence differs only by storing `value` at + that index; and +- throughout either behavior, the method remains sound. + +A caller seeking a no-panic result could prove the ordinary condition +`index < len`. Failure to prove that condition means the no-panic claim is +unavailable; it must not turn the safe call into undefined behavior. Whether +Anneal presents no-panic as a built-in policy, a property kind, or some other +construct remains open. + +## Local proof obligations + +For this example, a single symbolic execution could produce the following +obligations. That shared execution is illustrative rather than a commitment to +the final proof architecture. + +### Entry + +- Obtain `BufferInvariant(buffer, xs)` under the rules for a mutable borrow. +- Retain exactly one allocation capability while the invariant is open. + +### Out-of-bounds branch + +- Show that no raw-memory primitive is invoked. +- Show that the buffer state still represents `xs`. +- Under the artifact's unwind strategy, show that cleanup observes all + invariants and capabilities needed for soundness. +- Establish the contract's panic behavior. No normal-return postcondition is + claimed on this branch. + +### In-bounds branch + +- Derive every `replace_byte` guard from the branch condition and the opened + invariant; a user-written postcondition cannot substitute for a missing + provenance, initialization, or ownership fact. +- Apply the leaf's resource transition once. +- Re-establish `BufferInvariant(buffer, xs[index := value])` with the returned + allocation capability. +- Establish that the returned byte equals `xs[index]`. + +### Exit + +- Restore the invariant before returning control to safe code. +- Record dependencies between the user-defined `AbstractSequence` result and + the foundational soundness proof. + +Whether these facts are enforced through propositional arguments in translated +Lean definitions, sidecar WP theorems, or another complete mechanism remains +[unresolved](open-questions/source-model-adequacy.md). The requirement is that +Anneal cannot omit the primitive guard or a relevant control-flow branch. + +## Panic and unwind + +Because the bounds check occurs before the invariant is opened for mutation, +the panic branch has an unchanged buffer. With an unwind panic strategy, the +model must nevertheless follow cleanup and destruction far enough to prove +that resources remain valid and are consumed correctly. A panic is a source +behavior, not a verifier failure. + +Thus this method may satisfy soundness for every index while failing a blanket +no-panic claim. If a particular artifact uses `panic=abort`, the artifact and +claim differ; a proof for the unwind build is not automatically a proof for the +abort build. The example says nothing about whether outcome distinctions +become first-class axes in the final interface. + +Long-running behavior does not arise in this method. A server loop would use +the same general compositional idea but prove invariant preservation over each +finite execution prefix rather than require normal termination. + +## Global composition + +Assume that the artifact also proves: + +- every constructor establishes `BufferInvariant`; +- every other safe operation preserves it for all type-correct uses; +- destruction consumes its allocation exactly once; +- every call to a trusted memory or allocation leaf establishes that leaf's + guard; and +- no relevant item or control-flow edge is skipped. + +The local results then compose. Safe clients can use `ByteBuffer` without +examining its raw-pointer implementation or proving `index < len` for +soundness. The artifact is sound relative to the recorded primitive +specifications, translation adequacy, toolchain, and environmental assumptions. +If `AbstractSequence` is selected, clients may also use the proved sequence +contract without reopening the representation. + +This composition does not prove that a trusted leaf specification matches +Rust, that a user chose a useful abstract sequence contract, or that an +unchecked artifact variant has the same behavior. Those are different trust, +specification-adequacy, and artifact-identity questions. + +## An illustrative result record + +One fictional result for this example might be summarized as follows. The +record is intentionally compact; it demonstrates how the subject, claim, +evidence, and residual dependencies fit together rather than proposing a +schema. + +| Part | Illustrative contents | +| --- | --- | +| Compilation subject | `byte-buffer 0.1.0` at revision `abc123`; target `x86_64-unknown-linux-gnu`; feature `checked-replace`; compiler-resolved `cfg`; locked dependencies; `panic=unwind`; expanded generated Rust; relevant environment inputs | +| Claim | Soundness for the covered artifact, plus `AbstractSequence` for normal returns from `replace`; no claim over other targets, features, panic strategies, dependency resolutions, or downstream clients | +| Checked evidence | Constructors establish `BufferInvariant`; relevant methods preserve it; destruction consumes the allocation once; every covered memory-leaf call establishes its guard; `replace` proves its sequence contract | +| Residual dependencies | Trusted allocation, deallocation, and `replace_byte` specifications; no user axioms, incomplete proofs, prose justifications, or unsupported coverage in this fictional run | +| Provenance | Exact Anneal, Charon, Aeneas, rustc, LLVM, Lean, and proof-library identities and options, plus relevant host and target platform assumptions | + +If an incremental run relied only on prose for the `replace_byte` call, that +fact would move into the residual dependencies rather than checked evidence. +The eventual command-status policy remains open, but the conditional +dependency could not disappear from the reported result. See the canonical +[result and trust model](result-and-trust.md). diff --git a/anneal/agent_docs/glossary.md b/anneal/agent_docs/glossary.md new file mode 100644 index 0000000000..612b85cfec --- /dev/null +++ b/anneal/agent_docs/glossary.md @@ -0,0 +1,247 @@ + + +# Glossary + +This glossary gives short definitions for vocabulary stable enough to use +throughout the Anneal design. Proposed taxonomies remain in +[open design questions](design/open-questions/README.md) until accepted. + +## Assurance and properties + +**Soundness** + +: A guarantee that the covered Rust behavior has no undefined behavior. A safe + abstraction is sound only when every type-correct safe use admitted by its API + within the stated semantic and compilation envelope preserves that guarantee; + checking selected clients supports a narrower artifact claim. Soundness is + also a prerequisite for Anneal's promised source-to-model correspondence. + +**Unsafe (Rust)** + +: Rust syntax which marks an operation as carrying obligations the compiler + does not check, or marks a region in which the programmer accepts + responsibility for such obligations. The presence of `unsafe` code does not + by itself mean that the program is unsound. + +**Unsound** + +: Capable of causing Rust undefined behavior in a use which the relevant API + presents as permitted. An implementation may use `unsafe` operations and + still be sound when it establishes every required condition. + +**Property** + +: A proposition Anneal is asked to establish about a program or its behavior. + Examples include soundness, panic freedom, functional correctness, protocol + conformance, and resource bounds. + +**Property kind** + +: A class of obligations which may have its own contracts, invariants, + dependencies, and selection policy. Soundness is necessarily special; which + other classes receive first-class treatment remains open. + +**User-defined correctness property** + +: A property's intended meaning as supplied by the user rather than fixed by + Rust. Anneal can check a precise specification, but cannot decide whether it + expresses what the user actually wanted. + +**Specification adequacy** + +: Whether a specification is strong and faithful enough to justify the claim + made from it. In particular, a weak user contract must not erase a Rust + soundness requirement which Anneal is responsible for generating. + +## Claims, contracts, and composition + +**Claim** + +: The precise statement a verification result supports. It identifies the + Rust subject, properties, relevant behavior, coverage, and assumptions; “this + program is verified” without those qualifications is not a complete claim. + +**Contract** + +: The requirements under which an item may be used and the guarantees it + provides. A contract may mention multiple properties or execution outcomes; + its final source syntax remains open. + +**Precondition / caller obligation** + +: A requirement which must hold before an operation. At a call site, the caller + must establish each selected precondition—for example, that a pointer refers + to live memory. Rust safety requirements and ordinary functional assumptions + may require different source-language treatment even when Lean represents + both as propositions. + +**Postcondition** + +: A guarantee established after an operation for a relevant outcome. Which + outcomes carry which guarantees is part of the open property/outcome design. + +**Local guarantee** + +: What is proved about one item: under its preconditions, it establishes its + postconditions and meets the preconditions of the operations it invokes. + +**Global guarantee** + +: A claim obtained by composing local guarantees across the covered program, + relative to its explicitly reported trusted leaves and environmental + assumptions. + +**Robust safety** + +: The implementation remains sound under every type-correct safe use admitted + by its API within an explicitly stated semantic and compilation envelope. + This is the soundness-specific instance of the broader + contextual-refinement requirement. A result covering only selected clients + or calls is an artifact-level claim, not robust safety. + +**Contextual refinement** + +: Every implementation behavior visible to a context in the claim's quantified + envelope is permitted by the declared interface, including its stated effects + and transferred resources. Clients can therefore use the interface without + inspecting the private body. Checking the calls present in one compiled + program is narrower than proving this property for every client in such an + envelope; a result must say which claim it establishes. + +## Invariants and resources + +**Invariant** + +: A condition attached to a program abstraction which its rules require at + specified boundaries. Those rules determine when the condition may be + assumed, opened, consumed, and re-established. + +**Type invariant** + +: An invariant associated with values or storage of a type. Type invariants may + express arbitrary property kinds, and their enforcement must cover every + operation which can make the invariant relevant. + +**Trait invariant** + +: An invariant, of any property kind, which each relevant implementation of a + trait must establish and code with the corresponding trait bound may use. + +**Resource proposition** + +: A proposition whose proof carries ownership, permission, or another usage + discipline, so it cannot necessarily be copied or discarded like an + ordinary fact. Exclusive ownership and protocol state are common examples. + +**Capability** + +: Locally held authority or evidence which permits an operation, potentially + packaging facts about a heap, allocator, concurrency protocol, or external + environment. + +## Models, subjects, and evidence + +**Compilation subject (compilation artifact)** + +: One compiler-resolved Rust program with fixed target, features, `cfg` values, + dependencies, panic strategy, generated Rust, and relevant environment. It is + not a matrix of builds or merely Cargo's emitted native binary. + +**Verification result** + +: A reported claim about one compilation subject together with the checked + evidence and classified dependencies which support it. Proof-tool versions, + proofs, or assumptions can change the result without changing the Rust + subject. + +**Evidence graph** + +: The connected local contracts, proofs, call obligations, translation + evidence, and coverage evidence from which a result is composed. This is a + conceptual dependency graph; its concrete serialization remains open. + +**Residual dependency** + +: A dependency, gap, or failure which remains after Anneal evaluates the + evidence graph. It may condition or narrow a claim, or prevent Anneal from + establishing one. Examples include a trusted semantic leaf, an incomplete + proof, a prose justification, unsupported coverage, a toolchain dependency, + or an environmental assumption. Its status, role, and effect on the claim + must be explicit. + +**Source model** + +: The Lean-level semantics used to reason about the compiled Rust program. + Anneal must justify that this model is faithful for the claim it reports. + +**LLBC** + +: Charon's compiler-resolved, structured Rust intermediate representation. + Aeneas consumes LLBC, and current Anneal design work also trends toward + consuming it directly; the long-term integration boundary remains open. + +**Weakest-precondition specification (WP specification)** + +: A specification of what must hold before an operation so that a desired + continuation property holds afterward. Aeneas provides WP machinery and + tactics such as `step` and `step*` which Anneal should reuse when appropriate. + +## Trust and incompleteness + +**Trust** + +: A claim-relative reliance on a dependency whose correctness is not + established by checked evidence included in the result at the claimed + semantic endpoint. Trust can concern program semantics, correspondence and + integration, tool implementations, or the execution substrate. Not every + residual dependency is accepted as trust; some gaps and failures block a + claim instead. + +**Trusted computing base (TCB)** + +: Everything whose correctness must be assumed for a result to imply its + claim. This can include semantic leaves, translators, proof checking, + compilers, semantic assumptions, and relevant host and target hardware. + +**Trusted leaf** + +: An operation or external component whose specification is assumed rather + than proved from a body visible to the current verification. A deeper model + may replace that assumption later. + +**Axiom** + +: A proposition intentionally admitted without proof in the current model, + such as a specification of genuine external semantics or an Anneal-provided + primitive leaf. It must remain distinguishable in the result from an + unfinished proof or prose justification. Whether those categories share an + underlying Lean mechanism does not change their different meanings. + +**Incomplete proof** + +: A declared obligation whose proof has not yet been completed. It is different + from a claim that a proposition is inherently axiomatic. + +**Prose safety justification** + +: A human explanation, commonly a Rust `// SAFETY:` comment, accepted + temporarily in place of a selected formal proof during incremental adoption. + It is not a machine-checked theorem and must remain visible in the result. + +**Audit ledger** + +: The human- and machine-readable projection of the identities, residual + dependencies, coverage gaps, and trust assumptions which qualify a result. + Its exact schema remains open; its existence is required. + +**Fail closed** + +: Refuse to report a claim stronger than the available evidence supports. A + separately identified conditional or incremental result may still be useful + when every assumption and incomplete obligation is explicit. diff --git a/anneal/agent_docs/history/research-index.md b/anneal/agent_docs/history/research-index.md new file mode 100644 index 0000000000..1d213e1a5c --- /dev/null +++ b/anneal/agent_docs/history/research-index.md @@ -0,0 +1,184 @@ + + +# Anneal Research Index + +**Snapshot date: 2026-07-17.** + +Issues and pull requests record experiments, incomplete arguments, and views +which may already have changed. They are evidence and prompts for further +thinking, never normative design. Before relying on one, check its current +status, stack position, discussion, and diff. Normative constraints live in +[`agent_docs/design/`](../design/). + +## Coordinating issue + +[Tracking issue #3016](https://github.com/google/zerocopy/issues/3016) is the +best entry point into the work. At this snapshot it organizes work around: + +- making the implementation and infrastructure suitable for external + contribution; +- manually formalizing Rust from generated Lean in order to discover the + abstractions automation should eventually produce; +- separation-logic support in Aeneas; +- user-facing annotation and proof syntax; and +- internal code generation and organization. + +Its milestone and workstream wording is a planning snapshot, not a contract. +Use [principles](../design/principles.md), +[settled requirements](../design/settled-requirements.md), and the +[open-question index](../design/open-questions/README.md) to interpret it. + +## Open V2 and cross-cutting pull requests + +The following PRs were returned as open by a repository query on the snapshot +date. Many are GHerrit-managed stacked changes, so adjacent PRs can overlap or +be rebased together. Open status is not evidence that a change is absent from +this checkout: an open PR may be a stack ancestor or the current branch. +Inspect the tree and history to determine what is present, and use +[the current implementation state](../reference/current-state.md) for the +checked-in behavior rather than treating PR descriptions as authoritative. + +### Current orchestration and toolchain stack + +- [#3474: Compile merged util module at stack base](https://github.com/google/zerocopy/pull/3474) +- [#3463: Include Cargo in the exocrate Rust toolchain](https://github.com/google/zerocopy/pull/3463) +- [#3400: Add exocrate toolchain setup and `Toolchain` resolver](https://github.com/google/zerocopy/pull/3400) +- [#3401: Add Cargo workspace and target resolution](https://github.com/google/zerocopy/pull/3401) +- [#3402: Map workspace packages to `AnnealArtifact`s](https://github.com/google/zerocopy/pull/3402) +- [#3418: Add a pinned `charon_lib` dependency](https://github.com/google/zerocopy/pull/3418) +- [#3404: Add the Charon execution engine, `generate` CLI, and integration tests](https://github.com/google/zerocopy/pull/3404) +- [#3405: Chase out-of-tree dependencies for generation](https://github.com/google/zerocopy/pull/3405) +- [#3485: Prime Lake traces in one server traversal](https://github.com/google/zerocopy/pull/3485) +- [#3486: Audit cached Lean artifacts against clean builds](https://github.com/google/zerocopy/pull/3486) +- [#3403: Map compiler diagnostics back to Rust source](https://github.com/google/zerocopy/pull/3403) +- [#3436: Add an exocrate install-fixup hook](https://github.com/google/zerocopy/pull/3436) + +These changes are useful evidence about Cargo artifact identity, Charon +integration, diagnostics, cache portability, and the cost of dependency +chasing. They do not settle the long-term Anneal/Aeneas/Charon boundary. + +### Earlier or parallel V2 infrastructure + +- [#3361: Introduce Nix-based toolchain management](https://github.com/google/zerocopy/pull/3361) +- [#3362: Initial `setup` implementation](https://github.com/google/zerocopy/pull/3362) +- [#3378: Pass manifest and lockfile paths explicitly through exocrate](https://github.com/google/zerocopy/pull/3378) +- [#3487: Reorganize Anneal V1 and V2](https://github.com/google/zerocopy/pull/3487) + +Some effects of these proposals may already exist through different merged +commits. Read the current tree before assuming an open PR remains the intended +route. + +## Other open Anneal PRs: primarily V1 evidence + +These PRs were also open at the snapshot date. Most target the prototype or +pre-date the clean V2 boundary. They belong in historical research, not in the +V2 implementation plan by default. + +### Annotation, naming, and verification experiments + +- [#3478: Preserve module paths in generated function names](https://github.com/google/zerocopy/pull/3478) +- [#3477: Validate `isSafe` trait invariants while parsing](https://github.com/google/zerocopy/pull/3477) +- [#3321: Replace annotation syntax with verbatim Lean](https://github.com/google/zerocopy/pull/3321) +- [#3320: Translate and verify integration tests for the new syntax](https://github.com/google/zerocopy/pull/3320) +- [#3261: Add Lake package-management files](https://github.com/google/zerocopy/pull/3261) + +### Build, cache, and release experiments + +- [#3339: Remove redundant integration-test harness code](https://github.com/google/zerocopy/pull/3339) +- [#3338: Avoid copying Lean dependencies into the build directory](https://github.com/google/zerocopy/pull/3338) +- [#3337: Update integration tests for Nix](https://github.com/google/zerocopy/pull/3337) +- [#3336: Replace Docker with Nix](https://github.com/google/zerocopy/pull/3336) +- [#3335: WIP experimental changes](https://github.com/google/zerocopy/pull/3335) +- [#3334: WIP Docker-to-Nix conversion](https://github.com/google/zerocopy/pull/3334) +- [#3327: Download and install artifacts in parallel](https://github.com/google/zerocopy/pull/3327) +- [#3298: Adopt the Lake artifact cache and share workspace packages](https://github.com/google/zerocopy/pull/3298) +- [#3285: Overhaul release artifact and PR generation](https://github.com/google/zerocopy/pull/3285) +- [#3258: Roll prebuilts](https://github.com/google/zerocopy/pull/3258) +- [#3255: Reuse prebuilt Lean artifacts in generated workspaces](https://github.com/google/zerocopy/pull/3255) + +The repeated approaches are themselves evidence: setup latency, hermeticity, +Lake cache relocation, release provenance, and clean-build equivalence are +important engineering problems. No abandoned mechanism should be revived +solely because several old PRs explored it. + +## Issue map by research question + +The tracking discussion and repository issue search surfaced the following +threads. Open or closed status does not determine whether the underlying +question is settled. + +### Semantic coverage and artifact identity + +- [#3041: What about unreachable code?](https://github.com/google/zerocopy/issues/3041) + asks whether MIR elimination before Charon can hide code or produce a + misleading coverage claim. This is the concrete form of the question about + extraction before optimizations which assume or erase behavior. +- [#3017: Support `#[cfg]` in verification targets](https://github.com/google/zerocopy/issues/3017) + motivates making one resolved compilation artifact the source of truth. +- [#3350: Imported Rust types get unqualified names in generated specs](https://github.com/google/zerocopy/issues/3350) + illustrates the danger of a source-derived shadow naming system. + +### Trust, axioms, and proof completeness + +- [#3206: Ban axioms in non-axiom annotations](https://github.com/google/zerocopy/issues/3206) + is evidence for syntactic and semantic auditing of the Lean environment. +- [#3110: Visit all annotations and reject invalid locations](https://github.com/google/zerocopy/issues/3110) + concerns fail-closed coverage rather than only parsing supported locations. + +### Proof authoring and syntax + +- [#3201: Interactive proofs tracking](https://github.com/google/zerocopy/issues/3201) +- [#3062: Write Anneal specifications in Rust](https://github.com/google/zerocopy/issues/3062) +- [#3218: Make an entire annotation one Lean AST](https://github.com/google/zerocopy/issues/3218) +- [#3090: Pretty-print generated Lean](https://github.com/google/zerocopy/issues/3090) +- [#3086: Parse attributes with `chumsky`](https://github.com/google/zerocopy/issues/3086) +- [#3057: Support non-indented comments](https://github.com/google/zerocopy/issues/3057) + +These record syntax and tooling experiments. V2 has not selected a surface +language or proof location. + +### Hermeticity, packaging, and contributor workflow + +- [#3331: Manage all toolchain dependencies hermetically](https://github.com/google/zerocopy/issues/3331) +- [#3259: Build `Anneal.lean` independently in CI and locally](https://github.com/google/zerocopy/issues/3259) +- [#3256: Minimize dependencies of `Anneal.lean` and generated Lean](https://github.com/google/zerocopy/issues/3256) +- [#3266: Sanitize Cargo values used in Docker image creation](https://github.com/google/zerocopy/issues/3266) +- [#3420: Use standard base directories instead of polluting home directories](https://github.com/google/zerocopy/issues/3420) +- [#3060: Embed assets in the Anneal binary](https://github.com/google/zerocopy/issues/3060) + +Later Nix/exocrate work answers parts of these issues through different +mechanisms. Re-evaluate the underlying requirement rather than assuming the +issue's proposed implementation is still current. + +## Upstream reading + +- [Charon repository and documentation](https://github.com/AeneasVerif/charon) +- [Aeneas repository and documentation](https://github.com/AeneasVerif/aeneas) +- [Lean reference manual](https://lean-lang.org/doc/reference/latest/) +- [Rust Reference: behavior considered undefined](https://doc.rust-lang.org/reference/behavior-considered-undefined.html) +- [Rust Unsafe Code Guidelines reference](https://rust-lang.github.io/unsafe-code-guidelines/) +- [RustBelt project and papers](https://plv.mpi-sws.org/rustbelt/) + +Read the pinned Aeneas and Charon revisions used by `flake.nix`, not only their +latest default branches. Anneal collaborates with both projects, so upstream +changes are possible; current upstream behavior remains distinct from a +proposed extension. The concise Anneal-specific division of responsibility is +in [Aeneas and Charon](../reference/aeneas-and-charon.md). + +## Maintaining this index + +When refreshing the snapshot: + +1. record the new date; +2. query current issue and PR state rather than copying this list; +3. preserve historically useful links under an explicitly historical heading; +4. summarize what question a source informs, not what decision it allegedly + dictates; and +5. move a conclusion into normative documentation only after the project has + actually accepted it. diff --git a/anneal/agent_docs/history/v1-lessons.md b/anneal/agent_docs/history/v1-lessons.md new file mode 100644 index 0000000000..d5cddc906e --- /dev/null +++ b/anneal/agent_docs/history/v1-lessons.md @@ -0,0 +1,196 @@ + + +# Lessons from Anneal V1 + +Anneal V1 is the experimental prototype in `anneal/v1/`. V2 is a clean-room, +ground-up redesign. V1 supplies observations, examples, and failure modes; it +does not supply defaults. Copy V1 code or concepts only after showing that they +serve V2's principles and current requirements. + +This page deliberately distills lessons rather than preserving every +terminological clarification made while discussing V1. + +## What the prototype demonstrated + +### A useful end-to-end workflow is possible + +V1 connected Rust source, Charon, Aeneas, generated Lean, user-authored +contracts, and the Lean checker. It demonstrated that a Cargo-facing tool can +keep formal obligations close to Rust code, automate the toolchain, and map +many failures back into a workflow recognizable to Rust engineers. + +That validates the product direction, not V1's particular annotation grammar, +source scanner, generated theorem shapes, or directory layout. + +### Aeneas's functional model is a powerful default + +For supported Rust, Aeneas turns disciplined borrowing and mutation into +mathematical value transformations. V1 showed the ergonomic payoff of using +that model for ordinary control flow surrounding unsafe leaves. V2 should +build on maintained Aeneas and Lean abstractions where they remain faithful, +including weakest-precondition specifications and existing tactics. + +The lesson is not that every behavior must be forced into a pure transformer. +Resource and effect semantics must remain explicit whenever erasing them +could undermine soundness. + +### Local contracts can support global reasoning + +V1's precondition/postcondition structure exercised the intended composition: +a caller proves a callee's requirements, and a callee proves what it returns +or preserves. This remains the core local shape from which artifact-wide +soundness and user-defined properties should be assembled. + +V1 did not prove the complete adequacy theorem connecting arbitrary unsafe +Rust execution to its Lean model. That gap must remain visible rather than +being hidden by successful Lean compilation. + +## Designs which should **not** be inherited + +### Orthogonal progress and correctness duplicated work + +V1 split proofs into progress and correctness branches. The correctness branch +was conditional on successful execution, while the progress branch established +that execution succeeded. In practice: + +- the two proofs often repeated the same symbolic execution; +- the split did not compose naturally with Aeneas's WP specifications or its + `step` and `step*` tactics; and +- conditional correctness could be vacuous when progress was absent. + +V2 is leaning toward a shared Aeneas-style symbolic execution with obligations +for the relevant outcomes. The exact outcome/property architecture is still +open; V1 is evidence against making the orthogonal split the default, not a +decision that every verified function must terminate normally. + +Sound infinite execution, sound panic and unwind, and recovery after panic are +required use cases. + +### `isValid` was not enforced at mutation boundaries + +V1 attached an `isValid` predicate to a type and injected it into function +contracts, but safe Rust code could access or mutate invariant-carrying fields +without re-establishing the predicate. The mechanism was therefore knowingly +unsound and eventually required an explicit opt-in flag. + +V2 still requires type invariants for arbitrary property kinds. It must also +enforce opening and re-establishing them at every operation which can violate +them. Rust's proposed unsafe-fields feature could provide the language-level +boundary; Anneal-specific field access and mutation analysis is also in scope. +Waiting for upstream stabilization is not the only option. + +### `isSafe` expressed an architecture V1 did not enforce + +The durable idea behind V1's `isSafe` was that an unsafe trait implementation +establishes an invariant and generic code with the trait bound can consume it. +V1 documentation and implementation did not consistently enforce both halves. + +V2 requires trait invariants, like type invariants, to support arbitrary +property kinds. It must verify the invariant at every applicable +implementation site and expose exactly the corresponding assumption wherever +the trait bound is known. The final name and syntax are open. + +### Generated-Lean coupling was brittle + +V1 generated theorem signatures and proof scaffolding by predicting details +of Aeneas output: item names, tuple shapes, mutable-borrow returns, and special +treatment of `Unit` and `Never`. Small changes in Aeneas could require matching +Anneal changes or produce opaque Lean type errors. + +V2 should prefer compiler-resolved identities and maintained Aeneas interfaces +over textual surgery and a parallel source-derived ABI. This does not mandate +one interface: LLBC fields, library APIs, CLI modes, Lean syntax extensions, +and robust downstream adapters remain case-by-case options. + +### The source scanner could disagree with the compiler + +Parsing doc comments independently of rustc made it easy to lose the effects +of macro expansion, `cfg`, name resolution, aliases, and Cargo target +selection. A scanner can remain useful for source presentation, but semantic +claims must reconcile exactly with the compiler-selected artifact. + +### V1 annotation syntax is an experiment + +Indentation-sensitive Lean blocks in Rust documentation comments proved that +literate verification can work. They also exposed parser complexity, +formatting constraints, and leakage of Aeneas-generated names and proof +machinery. V2 is not committed to doc comments, indentation sensitivity, raw +Lean, Rust-like specifications, proof placement, or any V1 keyword. + +The audience requirement survives: ordinary Rust teams, including relatively +new engineers and engineers assisted by agents, must eventually be able to use +Anneal. Syntax should be judged by semantic clarity, diagnostics, +evolvability, and workflow—not resemblance to the prototype. + +## Trust-boundary lessons + +### `unsafe(axiom)` verified callers relative to a leaf + +V1's `unsafe(axiom)` made a function body opaque and trusted the user's +behavioral specification. It did not verify that body. This was useful for +composition and incremental coverage, but it left both the opaque +implementation and the specification in the TCB. + +V2's production objective is a small, explicit, shrinkable collection of +trusted leaves. Near-term leaves are expected to include some standard-library +unsafe operations and intrinsics, FFI, assembly, and raw-pointer operations. +Future formal ISA, foreign-language, or operational models may remove +individual leaves from the TCB. + +The syntax used for axioms is likely also needed by an Anneal standard library. +User-authored axioms will likely remain necessary for FFI for the foreseeable +future. It is open whether a foreign library author or each Rust consumer +normally owns those specifications. + +### Incomplete adoption needs a first-class status + +V1 supported `sorry`-based development and axiomatic boundaries, but a +production result needs to distinguish trusted external semantics from work +which is merely unfinished. Incremental adoption must also permit some +existing prose `// SAFETY:` justifications in place of formal proofs. + +Every such boundary must appear in an audit ledger. Whether an incomplete run +uses a separate command, profile, exit status, or result label remains open. + +### Specification adequacy cannot be delegated away + +Lean will prove a weak or vacuous specification. For Rust soundness, Anneal +must know or generate the required primitive safety obligations and ensure +that non-axiomatic specifications are adequate for them. Human review alone +is not an acceptable substitute for this mechanical guarantee. + +User-defined correctness properties have a different ground truth. Anneal can +ensure that a declared axiom is used and upheld, but cannot decide whether the +user chose the intended cryptographic, protocol, quantitative, or functional +property. + +## Product and reporting lessons + +- Rust's single `unsafe` axis is too coarse to express all property kinds. + Anneal must support dependencies among soundness and arbitrary additional + properties, while the degree of integration with Rust's existing unsafe + machinery remains open. +- Soundness is special and non-negotiable. Panic freedom, termination, + deadlock freedom, cryptographic correctness, resource bounds, and other + properties must not be silently conflated with it. +- A verification result needs an audit ledger. V1's opacity, axioms, `sorry`, + unsupported code, and toolchain assumptions were too easy to understand + only by inspecting implementation details. +- Diagnostics are part of semantic usability. When generated names or tuple + encodings leak into errors, users cannot reliably repair or review proofs. +- Incremental adoption is a core use case, but a partially checked result must + never masquerade as an unconditional one. + +## How to use V1 now + +Use `anneal/v1/` to reproduce experiments, inspect examples, and understand +why a V2 question exists. When citing it in a V2 design discussion, state the +observation rather than treating the V1 mechanism as precedent. If evidence +from V1 conflicts with [V2 principles](../design/principles.md) or +[settled requirements](../design/settled-requirements.md), V2 wins. diff --git a/anneal/agent_docs/reference/aeneas-and-charon.md b/anneal/agent_docs/reference/aeneas-and-charon.md new file mode 100644 index 0000000000..d58363fb5b --- /dev/null +++ b/anneal/agent_docs/reference/aeneas-and-charon.md @@ -0,0 +1,83 @@ + + +# Aeneas and Charon + +Anneal is being developed in collaboration with the +[Charon](https://github.com/AeneasVerif/charon) and +[Aeneas](https://github.com/AeneasVerif/aeneas) projects. This page records the +revision-sensitive facts coding agents need when working on that integration; +it does not assign future responsibilities among the projects. + +Upstream documentation and source are authoritative for a pinned release. This +page was last reviewed on 2026-07-17, when `anneal/flake.nix` selected Aeneas +release `nightly-2026.06.03`. Recheck the current pin before relying on a +supported construct, result type, or API described here. + +## Charon: compiler-integrated extraction + +Charon runs with the Rust compiler and exports Rust programs into LLBC (Low +Level Borrow Calculus), an intermediate representation designed for formal +reasoning. In the reviewed toolchain it provides compiler-resolved program +information after macro expansion and conditional compilation, including +resolved types, control flow, and source spans. + +Charon is not a verifier. Successful extraction means that it produced LLBC +for the selected compilation; it does not prove that the source is sound or +that a later Lean model is adequate. + +LLBC currently serves as Aeneas's semantic input. It can also provide +compiler-authoritative facts against which Anneal may reconcile annotations, +contracts, operations, calls, and diagnostics. Whether ordinary LLBC is +sufficient or another compiler-resolved interface is needed remains open. + +## Aeneas: functional translation and proof support + +Aeneas consumes LLBC and translates supported Rust into definitions in proof +assistants, including Lean. For a useful subset of Rust whose mutation follows +ordinary borrowing, this produces pure functional transformations rather than +an explicit whole-program heap model. Mutable-borrow translations carry the +information needed to reconstruct the final borrowed value. + +In the revision reviewed for this page, the Aeneas Lean library includes +weakest-precondition specifications and tactics such as `step` and `step*`. +Their exact interfaces and supported semantic envelope are revision-sensitive +and must be checked against the current pin. + +Aeneas does not by itself establish adequacy for every Rust program. Anneal's +questions about unsupported operations, resource-sensitive semantics, +exceptional execution, and the source-to-model correspondence are tracked in +the design documents linked below. + +## Checked-in Anneal integration + +The checked-in Anneal executable does not yet translate applications or verify +contracts. It currently packages and installs the pinned Aeneas distribution, +including the Aeneas and Charon executables and the Aeneas Lean libraries, and +constructs a Lean workspace which imports those libraries. See the +[current state](current-state.md) for the authoritative implementation summary. + +Anneal obtains the distribution from Aeneas's published +`nightly-2026.06.03` archive through `anneal/flake.nix`. The archive contains +Charon as part of the bundled toolchain; the checked-in setup does not maintain +a separate Charon pin. + +## Design questions owned elsewhere + +This reference intentionally does not decide what Charon should expose, what +semantics Aeneas should own, whether Anneal should extend either project, or +which downstream adaptations are acceptable. Those choices are governed by +the [project principles](../design/principles.md) and tracked in: + +- [Aeneas and Charon integration](../design/open-questions/aeneas-charon-integration.md); +- [source/model adequacy](../design/open-questions/source-model-adequacy.md); +- [memory, resources, and effects](../design/open-questions/memory-resources-and-effects.md); and +- [proof authoring and user experience](../design/open-questions/proof-authoring-and-user-experience.md). + +Experience from Anneal's earlier Aeneas integration is recorded separately in +[V1 lessons](../history/v1-lessons.md). diff --git a/anneal/agent_docs/reference/current-priorities.md b/anneal/agent_docs/reference/current-priorities.md new file mode 100644 index 0000000000..e8131d263f --- /dev/null +++ b/anneal/agent_docs/reference/current-priorities.md @@ -0,0 +1,108 @@ + + +# Current priorities + +**Snapshot date: 2026-07-17. This page is volatile and non-normative.** + +This page helps an agent apply Anneal's long-term principles to the early +implementation. It describes a useful near-term optimization lens, not an +accepted roadmap or a new ordering among the project's values. An explicit +task from the project authors, the [normative design](../README.md#normative-design), +and accepted decisions take precedence. + +## Starting point + +Read the dated [current implementation state](current-state.md) before planning +from this page. Establish what exists from the checked-in code and tests rather +than repeating a capability inventory here. + +Open and stacked pull requests explore nearby pipeline stages. They are useful +evidence about active engineering and integration pressure, but neither their +existence nor their implementation choices make them authoritative. Check the +current tree, tests, and history before claiming a capability has landed. The +[research index](../history/research-index.md) is only a dated navigation aid. + +## Near-term optimization lens + +Absent more specific direction, prefer work that turns the setup-only +foundation into a dependable, inspectable pipeline one reviewable stage at a +time. In practice, high-leverage work tends to have several of these +properties: + +- It makes the pinned Rust, Charon, Aeneas, Lean, and supporting artifacts + reproducible, installable, testable, or diagnosable. +- It connects a concrete Cargo compilation artifact to the next pipeline stage + through an explicit, machine-readable interface. +- It preserves compilation-subject identity and verification provenance rather + than relying on ambient state or an unreported default. +- It has a focused test that demonstrates the capability on the checked-in + branch and fails clearly when a dependency or stage is unavailable. +- It improves failure reporting and makes unsupported coverage or trust visible + rather than treating absence as success. +- It uses maintained Charon, Aeneas, Lean, Cargo, or rustc interfaces where + they fit, while keeping an upstream change in scope when that is the cleaner + long-term boundary. +- It is narrow enough to land without prematurely fixing an open semantic, + annotation, proof-authoring, or command-policy design. + +This lens favors durable enabling infrastructure over speculative completion +of the entire verifier. It does not make infrastructure more important than +soundness: any stage that begins making semantic claims must satisfy the +[settled requirements](../design/settled-requirements.md) and preserve the +[verification-result and trust model](../design/result-and-trust.md). + +## Working near the pipeline frontier + +Nearby work may involve Cargo target and artifact resolution, Charon execution, +LLBC transport, Aeneas generation, dependency discovery, Lake workspaces, +diagnostic mapping, or toolchain fixups. Treat that list as a description of +the engineering neighborhood, not a prescribed sequence or component boundary. + +For each change: + +1. Establish what is already present in this checkout; do not plan against a + sibling worktree or an open PR by accident. +2. Name the concrete input, output, and failure modes of the stage being added. +3. Preserve enough identity and provenance to relate its output to the fixed + [compilation subject and verification result](../design/result-and-trust.md). +4. Test the stage independently where practical and test the newly connected + boundary end to end. +5. Update current-state references only after the capability is checked in. +6. If the implementation would choose an answer recorded as open, pause for + explicit agreement or frame the work as a reversible experiment. + +In particular, pipeline plumbing must not incidentally settle the source of +annotation metadata, the Anneal/Aeneas/Charon ownership boundary, the unsafe +memory model, proof arguments versus sidecar theorems, or the final property +and outcome taxonomy. Those questions and their settled constraints live in +the [open-question index](../design/open-questions/README.md). + +## What not to optimize for yet + +Do not infer that the project currently wants: + +- a broad but unaudited claim of Rust coverage; +- compatibility with V1 syntax or architecture for its own sake; +- a polished `verify` success mode before its claim and trust reporting are + defined; +- local textual patches when a robust programmatic boundary is available; or +- premature generalization across target, feature, or configuration matrices + when the settled initial unit is one fixed compilation artifact. + +These cautions do not forbid experiments. They require experiments to be +identified as such and prevent temporary scaffolding from silently becoming a +project-wide decision. + +## Refreshing this page + +Revalidate this snapshot whenever the checked-in executable gains a pipeline +stage or project authors state a new near-term priority. Keep volatile work +sequencing here, current facts in the other `reference/` pages, and lasting +constraints or decisions in `design/`. Remove priorities that no longer help +choose work; do not preserve them as historical authority. diff --git a/anneal/agent_docs/reference/current-state.md b/anneal/agent_docs/reference/current-state.md new file mode 100644 index 0000000000..221704335a --- /dev/null +++ b/anneal/agent_docs/reference/current-state.md @@ -0,0 +1,157 @@ + + +# Current implementation state + +**Snapshot date: 2026-07-17.** + +This page describes the code checked into `anneal/`. It is a factual snapshot, +not a promise about the final architecture. Inspect the current tree and tests +when a detail matters; update this page when implementation changes make it +stale. + +## Status in one sentence + +Anneal currently constructs and installs its pinned external toolchain, but it +does not yet discover a Rust compilation subject, generate or check application +proofs, or produce a verification result. + +No invocation of the checked-in executable currently proves that an application +is safe or correct. + +## Repository boundary + +- `anneal/` contains the current clean-room implementation. +- `anneal/v1/` contains the historical prototype and has separate instructions. +- `exocrate/` installs and locates the versioned external toolchain archive. +- `.github/workflows/anneal.yml` contains jobs for both generations; passing a + V1 job does not establish a V2 capability. + +V1 remains useful implementation and design evidence. Its interfaces and +behavior are not defaults for the current implementation. + +## Implemented command path + +The compiled command currently supports `cargo-anneal setup`, including the +Cargo-plugin spelling `cargo anneal setup`. It selects either a local archive +provided with `--local-archive` or platform metadata from `Cargo.toml`, asks +`exocrate` to install or locate the archive, and reports the installation +directory. + +The checked-in remote archive URLs and hashes are placeholders. Development +and CI therefore use a locally constructed archive. `__ANNEAL_LOCAL_DEV` +selects a repository-local development installation; it is not a stable user +interface. + +`src/util.rs` contains helpers intended for later orchestration, but it is not +currently part of the compiled production command path. The presence of a +helper or an implementation in an open or sibling branch is not evidence that +the checked-in command exposes that capability. + +## Toolchain infrastructure + +`flake.nix` pins and packages a coupled Rust, Charon, Aeneas, Lean, Mathlib, and +supporting-tool environment for Linux and macOS on x86-64 and AArch64. It builds +Aeneas's Lean library, vendors Lake dependencies, prunes unused cache material, +normalizes selected paths and timestamps, and produces the omnibus archive used +by setup and CI. + +Supporting scripts rewrite vendored Lake metadata, prune the Mathlib closure, +derive coupled upstream versions and hashes, and check that release-relevant +flake outputs evaluate for every declared host system. These are substantial +toolchain and reproducibility capabilities; they are not an application +verification pipeline. + +## CI coverage + +The V2 CI path builds and layout-checks the omnibus archive, passes that exact +archive to the Rust test job, runs archive-dependent installation and Lake +cache tests, runs support-script tests, and evaluates the flake. Persistent Nix +caches written by pull requests are isolated from the cache populated by +trusted `main` builds. + +See [Development and CI](development-and-ci.md) for current commands, fixtures, +and workflow details. That page, the affected manifests, and the workflow files +are the closest sources of truth for validation. + +## Verification stages not yet implemented + +The checked-in executable does not yet: + +- select and identify a Cargo compilation subject; +- invoke Charon or consume LLBC; +- invoke Aeneas or generate a Lean model; +- resolve Anneal specifications or invariants; +- generate and track proof obligations; +- invoke Lean to check an application proof; +- map proof failures back to Rust source; +- compute property dependencies or coverage; or +- emit a scoped result and trust ledger. + +The intended high-level flow remains: + +```text +Cargo/rustc compilation subject + | + v + Charon extraction --> LLBC + | | + | v + | Aeneas Lean model + | | + +--------> Anneal contracts and obligations + | + v + Lean verification + | + v + scoped result and trust ledger +``` + +This diagram describes responsibilities, not settled APIs. Annotation +transport, unsafe-memory semantics, the Anneal/Aeneas/Charon boundary, proof +encoding, property representation, and command policy remain open. See the +[open-question index](../design/open-questions/README.md). + +## Current reporting and trust gaps + +Anneal does not yet produce a compilation-subject manifest, canonical result +identity, proof-coverage report, or audit ledger. It therefore does not yet +report residual trust in Charon, Aeneas, Anneal, Lean, rustc, LLVM, external +semantics, or host and target hardware. + +The toolchain archive pins many proof inputs, but the Rust toolchain used to +compile Anneal itself is not yet derived from the archive's pinned Rust +toolchain in CI. Placeholder download metadata also leaves the published +installation path incomplete. + +These are implementation limitations, not permission for a future verifier to +omit trust or coverage. The required result semantics live in +[Verification result and trust](../design/result-and-trust.md). + +## Using other sources + +Open issues and pull requests provide evidence about active work and design +pressure, but they do not describe the capabilities of this checkout. Before +claiming that a stage exists, inspect the checked-in implementation and tests. +Before treating an implementation choice as intended architecture, consult the +normative design documents and accepted decisions. + +The dated [current priorities](current-priorities.md) page is non-normative and +may help select near-term work. The [research index](../history/research-index.md) +is a navigation aid for issues and pull requests, not a capability ledger. + +## Updating this page + +Update this page when behavior lands, not when a pull request opens. Keep: + +- implemented facts here; +- commands and CI details in [Development and CI](development-and-ci.md); +- intended guarantees in `agent_docs/design/`; +- unresolved alternatives in `agent_docs/design/open-questions/`; and +- volatile work sequencing in [current priorities](current-priorities.md). diff --git a/anneal/agent_docs/reference/development-and-ci.md b/anneal/agent_docs/reference/development-and-ci.md new file mode 100644 index 0000000000..4c9c914706 --- /dev/null +++ b/anneal/agent_docs/reference/development-and-ci.md @@ -0,0 +1,146 @@ + + +# Development and CI + +Run V2 commands from `anneal/` or pass `--manifest-path anneal/Cargo.toml` +from the repository root. Commands rooted at `anneal/v1/` operate on the V1 +prototype. + +This page records the current workflow. It is not a stable CLI specification. + +## Fast local checks + +From the repository root: + +```bash +cargo test --locked --manifest-path anneal/Cargo.toml +PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover \ + -s anneal/tests -p 'test_*.py' +cargo fmt --manifest-path anneal/Cargo.toml --all -- --check +``` + +The repository-wide formatting entry point is: + +```bash +./ci/check_fmt.sh +``` + +That script intentionally formats V2, V1, `exocrate`, the workspace tools, +and Zerocopy. Use the narrower Cargo command while iterating on a V2-only +change; use the repository entry point before handing off a broad change. + +## Running setup locally + +The checked-in remote archive metadata is placeholder data. Exercise setup +with an archive built locally: + +```bash +mkdir -p anneal/target +nix build ./anneal#omnibus-archive-ci \ + --out-link anneal/target/anneal-exocrate.tar.zst +cargo run --manifest-path anneal/Cargo.toml -- \ + setup --local-archive anneal/target/anneal-exocrate.tar.zst +``` + +The archive argument is interpreted from the command's current directory. +When developing inside `anneal/`, use +`target/anneal-exocrate.tar.zst` instead. + +`__ANNEAL_LOCAL_DEV=1` selects the local-development installation location. +It is an internal switch and may change. + +## Archive-dependent Rust tests + +Tests behind the `exocrate_tests` feature expect this exact path relative to +`anneal/`: + +```text +target/anneal-exocrate.tar.zst +``` + +After building the archive, run: + +```bash +cargo test --locked --manifest-path anneal/Cargo.toml --all-features +``` + +These tests install the archive and build a small generated Lean workspace to +ensure the read-only, precompiled Lake cache can be reused. A missing archive +is a test-fixture failure, not evidence about Anneal's proof design. + +## Nix checks + +Evaluate every release-relevant flake package for every supported system: + +```bash +bash anneal/check-flake-eval.sh +``` + +Build and validate the archive for the current system: + +```bash +nix build ./anneal#omnibus-archive-ci +nix build ./anneal#omnibus-archive-layout-check --no-link +``` + +Evaluation across four systems is not a cross-platform build. CI's archive +builder builds for its current runner and separately checks that the package +graph evaluates for all declared systems. + +When rolling Aeneas, Rust, or Lean inputs, use +`anneal/chase-aeneas-versions.sh` as an aid. It downloads upstream artifacts +and computes coupled hashes. Review every resulting version and hash; Mathlib +cache output may require a subsequent fixed-output hash refresh. + +## CI topology + +`.github/workflows/anneal.yml` contains both generations: + +- `static_checks` runs V1 and V2 support-script tests and the V2 flake + evaluation check. +- `anneal_tests` and `verify_examples` are V1 jobs rooted at `anneal/v1/`. +- `v2_nix_cache` builds the V2 omnibus archive, checks its layout, and uploads + it for this workflow run. +- `v2` downloads that exact archive and runs + `cargo test --workspace --all-features` in `anneal/`. + +The Nix caches have a trust boundary. A cache saved by a trusted `main` build +may be reused by pull requests; a pull request writes only its PR-scoped +cache. Preserve that separation when changing cache keys or Actions steps. +The workflow artifact, not the persistent cache, is the cross-job handoff for +the current run. + +The release workflow currently publishes the V1 crate from `anneal/v1/` while +using V2's Nix flake to build omnibus toolchain archives. This mixed state is +intentional during the transition. Do not "simplify" paths without first +understanding which generation owns the crate and which owns the archive. + +## Platform-specific concerns + +- The flake declares Linux and macOS on x86-64 and AArch64. +- Linux builds use an FHS environment for downloaded Lean tooling. +- Ubuntu 24.04 CI temporarily adjusts an AppArmor user-namespace setting for + the sandboxed Nix build and restores it in an `always()` step. Preserve the + cleanup path. +- Lake metadata and trace files can contain build-machine absolute paths. + Archive construction deliberately rewrites them and makes the installed + Aeneas tree read-only. +- Archive size is checked against GitHub's release-asset limit. + +## Scope discipline + +Open stacked PRs contain scanner, Cargo resolution, Charon, generation, and +diagnostic work. When developing on a branch below those changes, use the +files actually present in the checkout as the source of truth. Do not add +tests or documentation for an API which only exists in another stack unless +the change explicitly depends on that stack. + +When a V2 change touches shared CI or release machinery, also run the relevant +V1 support tests. Otherwise, V1's large integration suite is not the default +validation target for V2 implementation work. diff --git a/anneal/v1/AGENTS.md b/anneal/v1/AGENTS.md index a0142e7794..18854514c3 100644 --- a/anneal/v1/AGENTS.md +++ b/anneal/v1/AGENTS.md @@ -6,11 +6,17 @@ license , at your option. This file may not be copied, modified, or distributed except according to those terms. --> -# Anneal +# Anneal V1 agent guide -> **Note to AI Agents:** This document is intended for agents **developing** the -> Anneal toolchain itself. If you are an agent **using** Anneal, please refer to -> the `llms.txt` and `docs/agent/` directory instead. +> **Historical prototype:** This file applies only to `anneal/v1/`. Anneal V2 +> is the clean-room redesign in the parent directory. V1 code, syntax, and +> architecture are not V2 defaults. Read the [V2 agent guide](../AGENTS.md) and +> [distilled V1 lessons](../agent_docs/history/v1-lessons.md) before carrying an +> idea from this subtree into V2. + +> **Note to AI Agents:** This document is intended for agents **developing the +> V1 prototype** itself. If you are an agent **using V1**, please refer to the +> `llms.txt` and `docs/agent/` directory instead. ## Basic commands diff --git a/anneal/v1/README.md b/anneal/v1/README.md index 66b7fd2811..a6e6bd5554 100644 --- a/anneal/v1/README.md +++ b/anneal/v1/README.md @@ -1,5 +1,12 @@ # Anneal +> **Historical V1 prototype:** This directory preserves Anneal V1 for +> maintenance, reproducibility, and design evidence. The active clean-room V2 +> redesign lives at [`anneal/`](../README.md). V1's syntax, architecture, +> soundness claims, and proof methodology are not commitments for V2. Coding +> agents comparing V1 with the current redesign must begin with the +> [current agent guide](../AGENTS.md). +

logo by tinyneonspark