docs(specs): probe a remote miss above a warm digest holder

What does this MR do?

Aligns S32's warm-digest rule with S13's Phase 2 and the shipped resolver: a healthy, eligible remote position above a digest's holder whose cache misses is Probed before the holder serves the read. At the Phase 1 short-circuit, a hosted miss, an excluded position (denied by a rule or failed for a data error), and an unhealthy remote count as definite; a healthy, eligible remote's miss does not.

The two specs disagreed before this change:

  • S32 "Warm digest pull short-circuits", the digest reference and the blob pull said a digest held by any upstream resolves at Phase 1 with no upstream call.
  • S13's short-circuit counted "a Miss" as a definite failure above the winner. S13's own Phase 2 bullet, a few lines below it, Probes every healthy remote position at or above the first fresh Hit whose Lookup was a Miss.
  • decisionForLookup in internal/virtual/decision.go follows Phase 2: a remote Miss is undecided, a hosted Miss is failed.

So with [remote_a, hosted_b] where only hosted_b holds a digest, the resolver Probes remote_a on every pull, and S32 said it would not. No test covers that shape, because Step 15's warm-digest test puts the holder at position 1. The S32 Step 18 validation found the gap: Step 18's harness lists hosted first for this reason.

The two readings

This MR takes "the spec is wrong". The alternative is "the code is wrong", so the spec author should confirm the direction:

  • Probe the remote (this MR). Lowest-position-wins holds for every format, and a remote's empty cache says nothing about its upstream. The cost: bytes are identical at every position for content-addressed reads, so the Probe decides only which position supplies the read (download booking, cache fill), not what bytes are served. A read pays nothing when every position above the holder is a hosted upstream, excluded, or unhealthy. A list such as [hosted_a, remote_b, remote_c] still pays one HEAD to remote_b on every pull of a layer only remote_c holds.
  • Skip the remote. Treat any Hit on a digest as a Phase 1 winner. That saves one HEAD per pull under a remote-first list, but it needs a resolver change in internal/virtual, which every virtual slice shares, and it moves which position records the download.

The new S32 Resolutions bullet ("A warm digest pull short-circuits past definite failures only, and a healthy remote's miss is not one") records the decision and its cost.

Changes

  • docs/specs/S13-virtual-remote-foundation.md: the short-circuit names a hosted Miss, an excluded position (denied by a rule or failed for a data error), and an unhealthy remote as definite, and a Miss or stale Hit on a healthy, eligible remote above N forces Phase 2.
  • docs/specs/S32-container-virtual.md: the digest reference, the blob pull paragraph, and the "Warm digest pull short-circuits" criterion carry the remote-miss condition, and the criterion gains the [remote_a, hosted_b] example. One new Resolutions bullet.

No code changes: the resolver already behaves as the amended text says.

e2e scenarios and user documentation

  • e2e catalog: no scenario is affected. The S32 Step 18 MR's virtual rows list hosted first.
  • User documentation: not affected. docs/user/ describes no resolution-order cost.

Related to #291 (closed)

🤖 Generated with Claude Code

Edited by Sylvia Shen

Merge request reports

Loading
Loading