You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Defect / goal:A chunk that lives in a seg: record can never be repaired or evacuated. custodian: backfill reads through the resolver, contained (635.4b.1) #695/custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 stop the three maintenance passes aborting on a segmented object, but they
deliberately write nothing: a repair obligation or a drain evacuation for a seg:-resident chunk
is refused and stays queued, every pass, forever. Nothing exits that state — the obligation is
not drained (which would be data loss), and no code path can move the placement, because the only
placement writers in the tree rebuild an inode record: reconstruction::repair_chunk builds plan.prior.chunk_map.as_flat()?.to_vec() and CASes the inode
(crates/custodian/src/reconstruction.rs:578-612), and rebalance::evacuate_chunk does the same
(crates/custodian/src/rebalance.rs:296-330). Neither can address a seg:<nonce>:<epoch>:<index> record at all. So a multipart-published object's redundancy decays
untended and a D-server decommission holding one of its fragments never converges. Both are
permanent states, which C-1 rules out as costs (docs/principles.md:137 §6 row Storage
lifecycle / reclamation, sourced to §5 C-1 at :109; the maintainer's standing rule of
2026-07-25; 0016:2802-2813; gc.rs:22-25).
Give the repair and evacuation passes an exact-bytes placement move that works in whichever
record holds the chunk, and switch both callers onto it.
Success criterion: the NEW file crates/custodian/tests/segmented_map_repoint.rs passes,
driven only through symbols visible on the base (post-child-1, post-custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697) — wyrd_custodian::{reconcile_step, Custodian, FencedZone, ReconstructionContext, RebalanceContext, Reconciled}, wyrd_custodian::desired_state::{set_lifecycle, DServerLifecycle, reconciliation_status, ReconciliationStatus}, wyrd_core::repair::{enqueue_repair, queued_repairs, repair_key}, wyrd_core::metadata::{seg_key, inode_key, encode, decode, MAX_VALUE_BYTES, SegmentGroup, SegmentRecord, SegmentRef, SegmentedMap, ChunkMap, InodeRecord, ChunkRef, EcScheme} — over in-memory MetadataStore / ChunkStore doubles. Four legs:
A seg:-resident under-replicated chunk is repaired. Seed a committed segmented
object (raw seg: records + a segmented root, never a committer) whose chunk has lost a
fragment, enqueue its repair, run reconcile_step with a ReconstructionContext. Assert: the
rebuilt fragment is on a healthy D server in a distinct failure domain; the seg: record's ChunkRef.placement now names it; the repair obligation is drained (queued_repairs no
longer contains it); the pass answers Changed; and the root record's bytes are unchanged
except as the move itself requires. Base behaviour: refused, obligation still queued, seg:
bytes unchanged → red.
A seg:-resident fragment is evacuated off a draining server. Same fixture shape with set_lifecycle(.., Draining) on the server holding a fragment; run reconcile_step with a RebalanceContext. Assert the fragment is copied to a non-draining server in a distinct
domain, the seg: record names it, the vacated position is orphan-marked, and the pass answers Changed. Base: refused, placement unchanged → red.
The ceiling refusal holds over a segmented record. A seg: record seeded just under MAX_VALUE_BYTES whose repoint would cross it: refused, record byte-identical, obligation
queued, pass non-certifying. (This leg is not independently red — pre-fix the move is
refused for the other reason, and child-1 already established the rule. It ships because it
pins the rule for the segmented arm, which child-1 cannot; do not count it as discriminating
evidence.)
Two committed references to the same ChunkId get one plan, not independent ones. Seed
two committed objects whose maps both name the same ChunkId, with a repair queued for it.
Assert the pass does not repoint or overwrite the same FragmentIds twice and does not orphan
copies the other object still references — neither object is left naming a fragment that was
reclaimed.
Legs (1), (2) and (4) are binding. Additionally, the DST repoint-versus-supersede property
ships in the existingcrates/dst/tests/custodian.rs (a new crates/dst/tests/*.rs would put #![cfg(madsim)] on the C4-verify invocation and change what the gate compiles): a repoint whose
pinned root generation or segment bytes changed under it commits nothing — neither the
placement nor any orphan mark — and the object is left naming a fragment that exists. Assert it
across the seed sweep, in both interleavings (repoint wins before the supersede's inode CAS;
repoint loses after it). C4-ci runs it; it is not the C4-verify discriminator.
Reproduction: on the target checkout, read the two binding commits with git -C ../wyrd show origin/main:crates/custodian/src/reconstruction.rs (:578-612) and git -C ../wyrd show origin/main:crates/custodian/src/rebalance.rs (:296-330) — both rebuild an inode record and can address no seg: record. Seed a committed segmented object (raw seg:
records + a segmented root) with a lost fragment, enqueue its repair, and run reconcile_step:
the obligation is refused and stays queued, every pass, forever.
Scope (one logical fix) / out of scope:one primitive and its two callers.
crates/core/src/metadata.rs — repoint_chunk: move one chunk's placement in the record that
holds its ChunkRef — flat inode or segment record. Both arms pin the exact bytes the
resolve read: the root generation, and additionally, for a segmented map, the segment record.
A stale-generation write is a Conflict, never a silent overwrite. The refusal and the conflict
paths write nothing at all. Route both arms through child-1's ceiling helpers — do not
re-implement the guard, and do not add a second ceiling constant.
The seam child-1 provides is stable by test, not by promise: custodian/tests/placement_ceiling.rs is on this child's base and C4-ci runs it, so replacing
the binding commits with repoint_chunk cannot silently regress the refusal, certification or
accounting rules. The rework this child does to child-1's two caller functions is inherent to
the parent's own design (the parent replaced those same commits) and bounded to them; the
outcome enums are crate-private (reconstruction.rs, rebalance.rs), so no public API
churns.
crates/dst/tests/custodian.rs — the repoint-versus-supersede property, added to the existing file.
Bounded memory. The move pins the bytes of one record at a time. Do not retain the
namespace's decoded chunks, and do not deep-copy a segmented root into every plan
(O(chunks × segments)).
Keep the CAS idiom of commit_chunk_map (metadata.rs:1741-1768) for the flat arm — version = prior.version + 1 and ..prior.clone() so ADR-0047 object metadata is preserved. Its own segmented refusal at :1748-1753stays; commit_chunk_map is not
what this slice changes.
Budget: ≤ 450 added semantic lines (non-blank, non-comment, non-mechanical), ≤ 6
files: core/src/metadata.rs, custodian/src/reconstruction.rs, custodian/src/rebalance.rs, custodian/tests/segmented_map_repoint.rs (new), dst/tests/custodian.rs, and at most one
of custodian/tests/{reconstruction,rebalance}.rs. A seventh file means the shape is wrong — in
particular, needing to edit backfill.rs, restore.rs, gc.rs or desired_state.rs means the
scope has drifted: STOP and hand back a proposed split.
Keep the discriminator assertion-red — HARD CONSTRAINT. The new test MUST NOT name repoint_chunk or any other symbol this patch introduces. The RED leg reverts production, so
such a reference makes the target fail to compile and the gate reports UNVERIFIABLE
(exit 77, run-verify.sh:450, :500) rather than a red. Drive everything through reconcile_step
and observe the store. MAX_VALUE_BYTES is base-visible and may be named.
Peer callsites Do MAY open — this is a composition slice; mirror them rather than invent a
shape:crates/core/src/metadata.rs:1741-1768 (commit_chunk_map, the flat CAS idiom); crates/custodian/src/reconstruction.rs:578-612 and crates/custodian/src/rebalance.rs:296-330
(the two binding commits being replaced, including the repair::repair_key delete and the gc::orphan_key puts that must stay in the same batch as the placement change); crates/core/src/metadata.rs:2619-2650 (resolve_chunk_map / ResolvedChunkMap — what a
caller holds after a resolve, and therefore what "the exact bytes the resolve read" can mean); crates/core/src/metadata.rs:1230-1300 (seg_key / seg_range_prefix / parse_seg_key, the
only sanctioned way to address a segment record); crates/custodian/tests/segmented_map_restore.rs:387-431 (seed_segmented / seed_damaged:
raw seg: + root seeding with a fixture self-check); crates/dst/tests/custodian.rs (the
existing seeded Tier-0 custodian properties, for the shape the new one must match).
External dependencies:typos, docs-renderer, cargo-deny, cargo-machete, cargo-mutants — the five [[doctor.checks]] ids in pdca.toml (cite by id, not by line — the parent
brief's line numbers were already stale at review, and the file churns). Named
because the prose and dependency-wall legs warn-skip locally while CI enforces them
(INTEGRATION §3), and because a cargo-deny older than 0.20.0 hard-fails the gating C4-ci row with
a message naming a flag rather than the stale tool. The DST leg needs no external tool — cargo
xtask ci supplies the madsim cfg and the seed sweep itself. Nothing else beyond the base Rust
toolchain: no Docker, no protoc, no live backend, no new dependency.
Child slice of #682, split during Plan.
seg:record can never be repaired or evacuated.custodian: backfill reads through the resolver, contained (635.4b.1) #695/custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 stop the three maintenance passes aborting on a segmented object, but they
deliberately write nothing: a repair obligation or a drain evacuation for a
seg:-resident chunkis refused and stays queued, every pass, forever. Nothing exits that state — the obligation is
not drained (which would be data loss), and no code path can move the placement, because the only
placement writers in the tree rebuild an inode record:
reconstruction::repair_chunkbuildsplan.prior.chunk_map.as_flat()?.to_vec()and CASes the inode(
crates/custodian/src/reconstruction.rs:578-612), andrebalance::evacuate_chunkdoes the same(
crates/custodian/src/rebalance.rs:296-330). Neither can address aseg:<nonce>:<epoch>:<index>record at all. So a multipart-published object's redundancy decaysuntended and a D-server decommission holding one of its fragments never converges. Both are
permanent states, which C-1 rules out as costs (
docs/principles.md:137§6 row Storagelifecycle / reclamation, sourced to §5 C-1 at
:109; the maintainer's standing rule of2026-07-25;
0016:2802-2813;gc.rs:22-25).Give the repair and evacuation passes an exact-bytes placement move that works in whichever
record holds the chunk, and switch both callers onto it.
crates/custodian/tests/segmented_map_repoint.rspasses,driven only through symbols visible on the base (post-child-1, post-custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697) —
wyrd_custodian::{reconcile_step, Custodian, FencedZone, ReconstructionContext, RebalanceContext, Reconciled},wyrd_custodian::desired_state::{set_lifecycle, DServerLifecycle, reconciliation_status, ReconciliationStatus},wyrd_core::repair::{enqueue_repair, queued_repairs, repair_key},wyrd_core::metadata::{seg_key, inode_key, encode, decode, MAX_VALUE_BYTES, SegmentGroup, SegmentRecord, SegmentRef, SegmentedMap, ChunkMap, InodeRecord, ChunkRef, EcScheme}— over in-memoryMetadataStore/ChunkStoredoubles. Four legs:seg:-resident under-replicated chunk is repaired. Seed a committed segmentedobject (raw
seg:records + a segmented root, never a committer) whose chunk has lost afragment, enqueue its repair, run
reconcile_stepwith aReconstructionContext. Assert: therebuilt fragment is on a healthy D server in a distinct failure domain; the
seg:record'sChunkRef.placementnow names it; the repair obligation is drained (queued_repairsnolonger contains it); the pass answers
Changed; and the root record's bytes are unchangedexcept as the move itself requires. Base behaviour: refused, obligation still queued,
seg:bytes unchanged → red.
seg:-resident fragment is evacuated off a draining server. Same fixture shape withset_lifecycle(.., Draining)on the server holding a fragment; runreconcile_stepwith aRebalanceContext. Assert the fragment is copied to a non-draining server in a distinctdomain, the
seg:record names it, the vacated position is orphan-marked, and the pass answersChanged. Base: refused, placement unchanged → red.seg:record seeded just underMAX_VALUE_BYTESwhose repoint would cross it: refused, record byte-identical, obligationqueued, pass non-certifying. (This leg is not independently red — pre-fix the move is
refused for the other reason, and child-1 already established the rule. It ships because it
pins the rule for the segmented arm, which child-1 cannot; do not count it as discriminating
evidence.)
ChunkIdget one plan, not independent ones. Seedtwo committed objects whose maps both name the same
ChunkId, with a repair queued for it.Assert the pass does not repoint or overwrite the same
FragmentIds twice and does not orphancopies the other object still references — neither object is left naming a fragment that was
reclaimed.
Legs (1), (2) and (4) are binding. Additionally, the DST repoint-versus-supersede property
ships in the existing
crates/dst/tests/custodian.rs(a newcrates/dst/tests/*.rswould put#![cfg(madsim)]on the C4-verify invocation and change what the gate compiles): a repoint whosepinned root generation or segment bytes changed under it commits nothing — neither the
placement nor any orphan mark — and the object is left naming a fragment that exists. Assert it
across the seed sweep, in both interleavings (repoint wins before the supersede's inode CAS;
repoint loses after it). C4-ci runs it; it is not the C4-verify discriminator.
integration branch — M4's is merged and deleted, and every core: segmented chunk map (0016 decision 7) — Flat | Segmented + seg:/seggrp: records + one resolver for every consumer #635 slice so far landed on
maindirectly.)
git -C ../wyrd show origin/main:crates/custodian/src/reconstruction.rs(:578-612) andgit -C ../wyrd show origin/main:crates/custodian/src/rebalance.rs(:296-330) — both rebuild aninode record and can address no
seg:record. Seed a committed segmented object (rawseg:records + a segmented root) with a lost fragment, enqueue its repair, and run
reconcile_step:the obligation is refused and stays queued, every pass, forever.
crates/core/src/metadata.rs—repoint_chunk: move one chunk's placement in the record thatholds its
ChunkRef— flat inode or segment record. Both arms pin the exact bytes theresolve read: the root generation, and additionally, for a segmented map, the segment record.
A stale-generation write is a
Conflict, never a silent overwrite. The refusal and the conflictpaths write nothing at all. Route both arms through child-1's ceiling helpers — do not
re-implement the guard, and do not add a second ceiling constant.
crates/custodian/src/reconstruction.rsandcrates/custodian/src/rebalance.rs— the twocallers stop refusing a
seg:-resident chunk (custodian: rebalance reads through the resolver, contained (635.4b.2) #696's and custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697's placeholder) and complete themove through the new primitive. The placement change, the discharge of the repair obligation,
and the orphan evidence for each displaced position stay one commit — do not split the batch
to fit the new primitive; if the primitive's shape makes that awkward, change the primitive.
custodian/tests/placement_ceiling.rsis on this child's base and C4-ci runs it, so replacingthe binding commits with
repoint_chunkcannot silently regress the refusal, certification oraccounting rules. The rework this child does to child-1's two caller functions is inherent to
the parent's own design (the parent replaced those same commits) and bounded to them; the
outcome enums are crate-private (
reconstruction.rs,rebalance.rs), so no public APIchurns.
crates/dst/tests/custodian.rs— the repoint-versus-supersede property, added to theexisting file.
shape, they do not name it):
not rebuild the cross-object claim-counting apparatus dropped at custodian: restore + desired-state through the resolver, contained and attributed (635.4a) #651's replan.
namespace's decoded chunks, and do not deep-copy a segmented root into every plan
(O(chunks × segments)).
(
results/issue_638/review-rejected.md:15-16). The refusal path writes nothing at all.commit_chunk_map(metadata.rs:1741-1768) for the flat arm —version = prior.version + 1and..prior.clone()so ADR-0047 object metadata ispreserved. Its own segmented refusal at
:1748-1753stays;commit_chunk_mapis notwhat this slice changes.
files:
core/src/metadata.rs,custodian/src/reconstruction.rs,custodian/src/rebalance.rs,custodian/tests/segmented_map_repoint.rs(new),dst/tests/custodian.rs, and at most oneof
custodian/tests/{reconstruction,rebalance}.rs. A seventh file means the shape is wrong — inparticular, needing to edit
backfill.rs,restore.rs,gc.rsordesired_state.rsmeans thescope has drifted: STOP and hand back a proposed split.
(child-1 — consume them, do not author them). The committer, the destination pre-mark, the
drain fence, rollback and resume (core: staged segment publication committer (635.6) #653). Proposal 0016's full segment-repoint precondition set
(
0016:669) isrequire(seg == prior)+require(inode == prior)+require(orphan:<P_new> == prior)(the destination pre-mark) +require_absent(desired:dserver:<S_new>)(the drainfence), bounded by
W_repoint. This slice ships only the first two. That is the issue's owncarve-out and it is a pre-declared sign-off item, not a surprise NEEDS-HUMAN: without the
pre-mark, a repoint that loses its CAS leaves the pre-written destination fragment unreferenced
— which is exactly the behaviour the flat path already has and documents today
(
crates/custodian/src/reconstruction.rs:610-614,crates/custodian/src/rebalance.rs:325-329:"the rebuilt fragments are collectable garbage"), reclaimed by GC's ordinary unreferenced
sweep. So this slice introduces no new stranding class; it extends an existing, settled one
to a second record shape. Do not implement the pre-mark or the fence here.
Also out: the chunk-id floor (core: chunk-id floor shrunk to what totality requires (635.5) #652, merged); restore and
desired_state(custodian: restore + desired-state through the resolver, contained and attributed (635.4a) #651, merged);gc.rs/scrub.rs(custodian: GC + scrub through the resolver with per-object containment (635.3) #650, merged);backfill.rs(custodian: backfill reads through the resolver, contained (635.4b.1) #695 — this slice does not touch it,which is exactly why it does not depend on that child). The read side generally: no new
resolving walk, no change to
resolve_chunk_map, no change to the containment rulecustodian: backfill reads through the resolver, contained (635.4b.1) #695/custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 land. Any new or edited ADR / spec / proposal (0016 is a draft and stays
untouched); any conformance-vector change; any new dependency.
repoint_chunkor any other symbol this patch introduces. The RED leg reverts production, sosuch a reference makes the target fail to compile and the gate reports UNVERIFIABLE
(exit 77,
run-verify.sh:450,:500) rather than a red. Drive everything throughreconcile_stepand observe the store.
MAX_VALUE_BYTESis base-visible and may be named.shape:
crates/core/src/metadata.rs:1741-1768(commit_chunk_map, the flat CAS idiom);crates/custodian/src/reconstruction.rs:578-612andcrates/custodian/src/rebalance.rs:296-330(the two binding commits being replaced, including the
repair::repair_keydelete and thegc::orphan_keyputs that must stay in the same batch as the placement change);crates/core/src/metadata.rs:2619-2650(resolve_chunk_map/ResolvedChunkMap— what acaller holds after a resolve, and therefore what "the exact bytes the resolve read" can mean);
crates/core/src/metadata.rs:1230-1300(seg_key/seg_range_prefix/parse_seg_key, theonly sanctioned way to address a segment record);
crates/custodian/tests/segmented_map_restore.rs:387-431(seed_segmented/seed_damaged:raw
seg:+ root seeding with a fixture self-check);crates/dst/tests/custodian.rs(theexisting seeded Tier-0 custodian properties, for the shape the new one must match).
typos,docs-renderer,cargo-deny,cargo-machete,cargo-mutants— the five[[doctor.checks]]ids inpdca.toml(cite by id, not by line — the parentbrief's line numbers were already stale at review, and the file churns). Named
because the prose and dependency-wall legs warn-skip locally while CI enforces them
(INTEGRATION §3), and because a cargo-deny older than 0.20.0 hard-fails the gating C4-ci row with
a message naming a flag rather than the stale tool. The DST leg needs no external tool — cargo
xtask ci supplies the madsim cfg and the seed sweep itself. Nothing else beyond the base Rust
toolchain: no Docker, no protoc, no live backend, no new dependency.
crates/custodian/tests/segmented_map_repoint.rs— a NEW file, not optional,completing the
segmented_map_*family (_consumers.rscustodian: GC + scrub through the resolver with per-object containment (635.3) #650,_restore.rscustodian: restore + desired-state through the resolver, contained and attributed (635.4a) #651, and the threeper-pass files
_backfill.rscustodian: backfill reads through the resolver, contained (635.4b.1) #695 /_rebalance.rscustodian: rebalance reads through the resolver, contained (635.4b.2) #696 /_reconstruction.rscustodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697). C4-verifyearns its red only from an added
*/tests/*.rs; appending to an existing file makes the gatetake the green-only branch (
run-verify.sh:454-464) and prove no red. The DST property incrates/dst/tests/custodian.rsand updates totests/{reconstruction,rebalance}.rsship inaddition; C4-ci covers them, and the modified DST file is not compiled by the discriminator
run (no
--cfg madsimis imposed on the gate,run-verify.sh:112-120). Re-runrun-verify.sh --classifyat Plan to confirm the invocation.custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 (rebalance and reconstruction containment) — not custodian: backfill reads through the resolver, contained (635.4b.1) #695 (backfill), which this slice does
not touch. Those are proposal-external, so they ride in the
Depends on (merged):field above —the split parser passes it through verbatim (it is not one of its ordering fields) and
flowenforces it via
merged.is_merged, holding this bundle until their PRs are merged into thebase. Plain
Depends onwould not: both are already COMPLETE bundles with unmerged PRs. Thisslice completes the refusal path custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 introduce: its callers are the two sites they
leave refusing, and it edits the same two production files, so building on a base without them
would collide on every hunk. Under
wave_mode = "merge"(pdca.toml:90) with[driver].auto_merge = falsethe driver does not merge at the wave boundary — it stops andthe human merges the wave's PRs, then re-runs; once merged, the ref C4-verify resolves is
the base the PR opens against and genuinely contains them (INTEGRATION §2, "How
C4-verifyresolves the base"). If custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697 are not accepted and merged, hold this bundle — do not
rebuild it against a base without them and do not let it absorb their read side; that is
precisely the un-splitting that closed PR feat(core,custodian,server): segmented chunk maps beyond one value #647. Same rule for child-1 (in-batch, the wave
boundary stop covers it; if this child is ever run in a separate later batch, hand-add child-1's
real id to
Depends on (merged)first). Never share a wave with Brief — multipart record family + validating decoders (654 split 2/3) #692 — it carries what wascore: multipart record family + state machine as pure functions (636.1) #654's
PendingEntryextension intometadata.rsplusdst/tests/custodian.rs, both in thischild's file set, and its brief declares
Conflicts with: 682; post-accept, repoint that atthis child's real id. Cite by symbol, not by number — the base WILL have advanced: custodian: rebalance reads through the resolver, contained (635.4b.2) #696/custodian: reconstruction reads through the resolver once per pass, contained (635.4b.3) #697
rewrite
rebalance.rsandreconstruction.rs, child-1 edits both plusmetadata.rs, and Brief — multipart record family + validating decoders (654 split 2/3) #692(if it lands first) inserts two fields into
PendingEntryatmetadata.rs:1528, shifting everycitation below it. The constants at
:322–:354sit above the insertion and are unaffected.closed/rejected work.
git -C ../wyrd log origin/main -- crates/core/src/metadata.rs→ mostrecently
b083ec4(core: chunk-id floor shrunk to what totality requires (635.5) #652),11aa85f(custodian: GC + scrub through the resolver with per-object containment (635.3) #650),99c7fcf(core,custodian,server: shared segmented-map resolver + read paths (635.2) #649, the shared resolver — the premisethis builds on),
bbdb7c5(core: ChunkMap Flat|Segmented record shape + seg:/seggrp: key helpers (635.1) #648 follow-up),3e05891(core: ChunkMap Flat|Segmented record shape + seg:/seggrp: key helpers (635.1) #648, the segmented record shape). Noneimplements a placement move in a
seg:record.git -C ../wyrd log origin/main -- crates/custodian/src/{reconstruction,rebalance}.rs→ the repair/evac loops (M3.6 — Reconstruction custodian (commit-point-atomic) + repair-vs-serve priority #144/M3.7 — Rebalance + declarative drain/decommission + capacity telemetry #145) and theirfixes (Reconstruction telemetry: time_to_repair is an absolute instant, and reconstruction_repaired over-counts successes by the Aborted count #197 "don't count aborted repairs as successes", PR fix(custodian): don't count aborted repairs as successes #238; Rebalance evacuation ignores identity-placement fallback — pre-M3 fragments on a draining D-server are never evacuated #346 identity-placement
fallback; Maintenance loops should reject malformed placement lengths instead of silent identity fallback #348 malformed placement). No open PR touches these paths. Closed/rejected: PR
feat(core,custodian,server): segmented chunk maps beyond one value #647 (CLOSED 2026-07-30, unmerged) is the un-split ancestor and contained a
repoint-shapedwrite; it was closed for size and reviewability, not direction. Its custodian-local
crates/custodian/src/resolve.rshas been superseded by the shared resolver — do notreintroduce it. Within the harness,
results/issue_638/review-rejected.md:15-16records thestanding, four-times-rejected rule that a losing/late write is not retracted; do not
re-litigate it.