link sync store: fence when identify gives no capability list

Merged
TE
1d ago
+22-6

Follow-up 1 of #35652, from the Codex review that gave SHIP on #34604.

What it fixes

When a machine's identify answer succeeds but its capabilities are missing or not a list, fetch_served read it as Some(false): "this machine serves no blob fetch". The push then skipped the fence, so an older blob.fetch job still running there could commit files over what this push writes. A missing list says nothing about what the machine serves, so it is now None, and the push takes fence_unknown (the path already used when identify does not answer at all). A machine whose list is present and lacks blob-fetch-v2 is still Some(false), unchanged.

The decision is pulled out of fetch_served into serves_fetch(&Value) so it can be tested without a socket.

Test

cargo test -p cmux-tui --lib an_identify_answer_without_capabilities (hosted, ./scripts/verify-cmux-tui-hosted.sh --filter):

  • Red on the test-only commit b2e3c83 (run 41878360641): left: Some(false), right: None.
  • Green on the head: the hosted run for link::sync_cli::store (result in a comment below).

Observed / Not run

  • Observed: the red above, from the hosted run's log.
  • Not run: the link_sync_store end-to-end test, which has no fixture for an identify answer without capabilities. This change only affects that case.

risk: low (one branch of a capability check, toward the cautious path).

Changelog

none

Agent session: agent session

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fences a push when a machine's identify succeeds but its capabilities are missing or not a list, closing a window where an older blob.fetch job could still commit files over the push's writes.

Previously a missing or non-list capabilities field was read as Some(false) ("serves no blob fetch") and the push skipped the fence. It now reads as None and the push takes fence_unknown, the same path used when identify does not answer at all. A present list that lacks blob-fetch-v2 is still Some(false), unchanged.

The capability check is pulled out of fetch_served into serves_fetch(&Value) so it can be tested without a socket, with a new unit test covering the missing, malformed, and present-list cases.