Skip to content

Load manifest hashes as lowercase so every verify site agrees (#707) - #1163

Merged
Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
arch-refactor/707-manifest-hash-case
Oct 8, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
arch-refactor/707-manifest-hash-case

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #707

Summary

PatchFileInfo's beforeHash/afterHash are now lowercased when a manifest is deserialized. Every consumer then sees one spelling: agent-mode apply and rollback verification, blob names and vendored pins. Before this change, a manifest that spelled its hashes in uppercase passed blob download, which compares case-insensitively, and then failed apply and rollback verification. Those compare the computed lowercase git-sha256 with ==, so they reported HashMismatch for bytes that matched.

Why

  • Issue #707, register row C41 (register), living document doc/07-infra-agent.md C41: the hash case rule is decided separately at each comparison site. This PR takes the issue's recommended fix, "normalize at the boundary", which sets the rule once at load instead of adding a case-insensitive helper at every site.
  • Leverage: B 1 (Agent-mode apply and rollback reject a manifest hash in uppercase hex that blob download accepts as valid #707), U 0, D ≈ 1 (one case rule instead of one per site), R L. Every higher-ranked item touches files that open arch-refactor/* or agent/fix-* PRs also change (see the refactor register's Queue).

What changed

Also included

b920a55 ports #1162's fix for the oracle selftest temp-path collision, which failed this PR's coverage job (e2e_vendored_production). It is test-only and becomes a no-op once #1162 merges.

Deleted

Nothing in production. The diff is +18 production lines (including the doc comment) and +112 test lines for #707. The comparison helpers this rule makes redundant are in files that open PRs change (see above).

Behavior

  • An uppercase-hash manifest now verifies, applies and rolls back, the same as the lowercase one.
  • A manifest that is written back after load stores the lowercase spelling.
  • On a case-sensitive filesystem, a blob that was previously saved under an uppercase name is no longer found by that name. It is fetched again under the lowercase name, and GC treats the old file as unreferenced. Lowercase manifests, which is everything the API emits, are unchanged.

Test evidence

  • New manifest::schema::tests::test_patch_file_info_loads_hashes_lowercase and test_uppercase_manifest_hashes_apply_and_roll_back, which reads a manifest from disk, then runs verify, apply, rollback-verify and rollback for the lowercase and uppercase spellings.
    • Red on main's rule, with the attribute removed: upper=true: VerifyResult { status: HashMismatch, current_hash: "e5c1…", expected_hash: "E5C1…" }. 2 failed.
    • Green on this branch: 17/17 manifest::schema.
  • cargo test -p socket-patch-core --lib: 5788 passed. The 4 failures are the known root-only sandbox tests that also fail on main (copy_tree::relax_loop_must_not_traverse_symlinked_root, vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry, pypi_poetry::wire_write_failure_…, pypi_requirements::wire_failure_rolls_back_…).
  • cargo test -p socket-patch-cli --all-features --test e2e_vendored_production: 49 passed, 13 ignored (production).
  • cargo clippy --workspace --all-features -- -D warnings: clean.

Risk

Low. One serde attribute on the load path. API-emitted manifests are already lowercase, so they are unaffected.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FkC1KYiCBhfqT5US5QMvSD


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko Mikola Lysenko (mikolalysenko) added refactor Structural change: duplicated code or logic, missing abstraction, layering, dead code arch-refactor PR opened by the scheduled architecture refactor routine labels Oct 8, 2026
A manifest whose beforeHash/afterHash are spelled in uppercase hex
passed blob download (which compares case-insensitively) but then
failed apply and rollback verification, which compare the computed
lowercase git-sha256 with ==. The same bytes were reported as a hash
mismatch.

Lowercase both hashes when a PatchFileInfo is deserialized, so every
comparison site, blob name and vendored pin sees one spelling. A
manifest written back after load carries the lowercase spelling.

Fixes #707.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 8, 2026 20:12
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
Assisted-by: Claude Code:claude-opus-5-5

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

The coverage job failed on e2e_vendored_production: tests/common is
compiled twice into that binary, so its oracle selftests ran twice in
one process and clobbered each other's PID-named /tmp scratch files.
This is the same change as #1162 (per-test tempfile::tempdir()), so
the flake stops blocking this PR; it no-ops once #1162 merges.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] coverage failed on 2388907 with error: 1 target failed: -p socket-patch-cli --test e2e_vendored_production. This failure doesn't come from this PR. That binary's production tests are all #[ignore]d, and the binary passes locally (49 passed). This is the oracle-selftest temp-path collision that #1162 diagnoses: tests/common is compiled twice into the binary, and both copies use the same PID-named /tmp paths. It also evicted merge-group runs on main.

I ported #1162's change (a per-test tempfile::tempdir() in tests/common/mod.rs) into this PR as b920a55. The suite passes locally with it, and it becomes a no-op once #1162 merges.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit b920a55. Configure here.

@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 8, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Burn-down agent: labeled Ready for review at b920a55.

  • CI: all check suites on the head are success (381 check runs, ci-ok success); no main-wide failures.
  • Bugbot: reviewed this head (Cursor check success); no unresolved review threads.
  • Mergeable, no CHANGELOG.md change.
  • Slack announcement not sent this run (Slack send tool unavailable); the next run will retry.

Generated by Claude Code

Merged via the queue into main with commit 527814b Oct 8, 2026
382 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the arch-refactor/707-manifest-hash-case branch October 8, 2026 22:18
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-refactor PR opened by the scheduled architecture refactor routine Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review refactor Structural change: duplicated code or logic, missing abstraction, layering, dead code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent-mode apply and rollback reject a manifest hash in uppercase hex that blob download accepts as valid

3 participants