Skip to content

custodian: Reconciled::Blocked's contract says "could not be read", but three in-flight loops also return it for work they refuse #701

Description

@eduralph

Carved out of #697 during a re-plan (2026-08-07). Raised as an ESCALATED (not rejected) review
finding on round 5 (wyrd-pdca results/issue_697/review-rejected.md, the reconciliation.rs:25
entry) and as a C1 NEEDS-HUMAN. It is a documentation/contract question shared by three in-flight
slices, so it belongs to none of them.

The contract as written

Reconciled::Blocked's rustdoc names exactly one condition
(crates/custodian/src/reconciliation.rs:25-28, origin/main @ 339da46):

The loop ran over everything it could read and refuses to certify the rest: at least one
committed object's chunk map could not be read (crate::gc::ReferenceSet::unresolvable), so the
reference set the loop reasoned over is incomplete.

That is accurate on main today: the only two producers are GC (gc.rs:241, doc'd at :135) and
scrub (scrub.rs:210, doc'd at :72), and both return it for an unreadable object. The doc
also cites gc::ReferenceSet::unresolvable — a type the other loops cannot use.

Where it stops being accurate

#695 (backfill), #696 (rebalance) and #697 (reconstruction) each move their loop onto the shared
resolver and each answer Blocked for a second condition: work the pass read successfully
and may not perform — a fill / evacuation / repair whose chunk lives in a seg: record, pending
#682's segmented write path. The object's map was read fine; what the pass refuses is the write.

Each of the three briefs pins that answer, for the same reason the doc's own second paragraph gives:
Satisfied would tell the operator the store converged while an obligation is still owed, and
Changed would claim a convergence that did not happen. So the outcome is right and the sentence
is now too narrow — the general fact is:

the loop refuses to certify because something it was responsible for is unaccounted, whether
because it could not be read or because this slice may not perform it.

Why it is not fixed inside any of the three slices

All three are budgeted at exactly two files (<loop>.rs + one new test file), with an explicit
"a third file means the shape is wrong: STOP and hand back" backstop — deliberately, after seven
rounds on the un-split #681 and five on each child. reconciliation.rs is a third file for every one
of them, and whichever slice took it would leave the other two contradicting the doc until it merged.
Round 5 of #697 wrote the exact replacement hunk out in build-notes.md §5 rather than land it.

What this issue asks for

  1. Generalise the Blocked rustdoc so it states the claim ("the loop will not certify: something it
    was responsible for is unaccounted"
    ) and lists the reasons, with the unreadable-object case as
    one instance rather than the definition; drop or soften the gc::ReferenceSet::unresolvable
    citation so it does not read as the only route.
  2. Check reconcile_step's companion doc (reconciliation.rs:101) and the two existing producer
    docs (gc.rs:135, scrub.rs:72) for the same narrowing — the per-loop docs may stay specific,
    the enum's may not.
  3. Decide whether "refused pending core,custodian: repoint_chunk — ceiling-safe placement moves in a segmented record (635.4c) #682" deserves to be distinguishable from "unreadable" at the
    outcome level or only on the audit seam. The three slices assume only on the audit seam
    (each publishes its own action + counter), which keeps least_certified a three-way fold; a
    fourth variant would ripple into reconcile_step and the drain-status surface.

Doc-and-contract only — no behaviour change is being asked for here. A review finding against #695,
#696 or #697 on this wording is to be pointed at this issue, not fixed in-PR (AGENTS.md:204-205).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions