Engine execution layer for V2 replication protocol: - RebuildInstaller: full state handoff (dirty map, WAL, superblock, flusher) - TruncateToLSN: exact safety predicate (checkpointLSN == truncateLSN), ErrTruncationUnsafe escalation to NeedsRebuild - SyncReceiverProgress: unconditional Store for post-rebuild alignment - V2StatusSnapshot: CommittedLSN = nextLSN-1 for sync_all V2 bridge real I/O executors: - TransferFullBase: TCP streaming + RebuildInstaller + second catch-up - TransferSnapshot: SHA-256 verified streaming to disk - TruncateWAL: ErrTruncationUnsafe detection + escalation - StreamWALEntries: rebuild-mode TCP apply Engine executor interfaces: - CatchUpIO.TruncateWAL, RebuildIO.TransferFullBase returns achievedLSN - CatchUpExecutor truncation-only skip, NeedsRebuild escalation - RebuildExecutor uses achievedLSN for progress tracking Design docs reorganized: superseded planning docs removed, protocol truths and closure map added. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
22 KiB
Phase 08
Date: 2026-03-31 Status: complete Purpose: convert the accepted Phase 07 product path into a pre-production-hardening program without reopening accepted V2 protocol shape
Why This Phase Exists
Phase 07 completed:
- a real service-slice integration around the V2 engine
- real storage-truth bridge evidence through
v2bridge - selected real-system failure replay
- the first explicit product-path decision
What still does not exist is a pre-production-ready system path. The remaining work is no longer protocol discovery. It is closing the operational and integration gaps between the accepted product path and a hardened deployment candidate.
Phase Goal
Harden the first accepted V2 product path until the remaining gap to a production candidate is explicit, bounded, and implementation-driven.
This phase doc is the canonical hardening contract for sw and tester.
Use phase-08-log.md for deeper engineering process, alternatives, and implementation detail.
Algorithm note:
- the accepted V2 algorithm / protocol shape is treated as fixed for this phase
- remaining work is engineering closure over real Seaweed/V1 runtime paths under V2 boundaries
- do not reopen protocol design unless a live contradiction is found
Scope
In scope
- real master/control delivery into the engine service path
- integrated engine -> executor ->
v2bridgeexecution closure - rebuild execution closure for the accepted product path
- operational/debuggability hardening
- concurrency/load validation around retention and recovery
Out of scope
- new protocol redesign
RF>2coordination- Smart WAL optimization work
- broad performance tuning beyond validation needed for hardening
- full V1 replacement rollout
Phase 08 Items
P0: Hardening Plan
- convert the accepted
Phase 07product path into a hardening plan - define the minimum pre-production gates
- order the remaining integration closures by risk
- make an explicit gate decision on committed truth vs checkpoint truth:
- either separate
CommittedLSNfromCheckpointLSNbefore a production-candidate phase - or explicitly bound the first candidate path to the currently proven pre-checkpoint replay behavior
- either separate
Status:
- planning package accepted in this phase doc
- first hardening priorities are fixed as:
- real master/control delivery
- integrated engine -> executor ->
v2bridgecatch-up execution chain - first rebuild execution path
- the committed-truth carry-forward is now a required hardening gate, not just a note:
- either separate
CommittedLSNfromCheckpointLSNbefore a production-candidate phase - or explicitly bound the first candidate path to the currently proven pre-checkpoint replay behavior
- either separate
- at least one real failover / promotion / reassignment cycle is a required hardening target
- once
P1andP2land, the accepted failure-class set must be replayed again on the newly unified live path - the validation oracle for
Phase 08is expected to reject overclaiming around:- catch-up semantics
- rebuild execution
- master/control delivery
- candidate-path readiness vs production readiness
- accepted
Reference:
sw-block/docs/archive/design/phase-08-engine-skeleton-map.mdis the implementation-side skeleton map for this phase- it is subordinate to
sw-block/design/v2-protocol-truths.mdand thisphase-08.md; use it for module layout, execution order, interim fields, hard gates, and reuse guidance
P1: Real Control Delivery
- connect real master/heartbeat assignment delivery into the bridge
- replace direct
AssignmentIntentconstruction for the first live path - preserve stable identity and fenced authority through the real control path
- include at least one real failover / promotion / reassignment validation target on the chosen
sync_allpath
Technical focus:
- keep the control-path split explicit:
- master confirms assignment / epoch / role
- bridge translates confirmed control truth into engine intent
- engine owns sender/session/recovery policy
blockvoldoes not re-decide recovery policy
- preserve the identity rule through the live path:
ReplicaID = <volume>/<server>- endpoint change updates location but must not recreate logical identity
- preserve the fencing rule through the live path:
- stale epoch must invalidate old authority
- stale session must not mutate current lineage
- address change must invalidate the old live session before the new path proceeds
- treat failover / promotion / reassignment as control-truth events first, not storage-side heuristics
Implementation route (reuse map):
- reuse directly as the first hardening carrier:
weed/server/master_grpc_server.goweed/server/volume_grpc_client_to_master.goweed/server/volume_server_block.goweed/server/master_block_registry.goweed/server/master_block_failover.go
- reuse as storage/runtime execution reality:
weed/storage/blockvol/blockvol.goweed/storage/blockvol/replica_apply.goweed/storage/blockvol/replica_barrier.goweed/storage/blockvol/v2bridge/
- preserve the V2 boundary while reusing these files:
- reuse transport/control/runtime reality
- do not inherit old policy semantics as V2 truth
- keep engine as the recovery-policy owner
- keep
blockvolas the I/O executor
Validation focus:
- prove live assignment delivery into the bridge/engine path
- prove stable
ReplicaIDacross address refresh on the live path - prove stale epoch / stale session invalidation through the live path
- prove at least one real failover / promotion / reassignment cycle on the chosen
sync_allpath - prove the resulting logs explain:
- why reassignment happened
- why a session was invalidated
- which epoch / identity / endpoint drove the transition
Reject if:
- address-shaped identity reappears anywhere in the control path
- bridge starts re-deriving catch-up vs rebuild policy from convenience inputs
- old epoch or old session can still mutate after the new control truth arrives
- failover / reassignment is claimed without a real replay target
- delivery claims general production readiness rather than control-path closure
Status:
- accepted
- real assignment delivery into the V2 path is now proven through
ProcessAssignments() - accepted evidence includes:
- live assignment -> engine sender/session creation
- stable remote
ReplicaID = <volume>/<ServerID> - address-change identity preservation through the live path
- stale epoch/session invalidation through the live path
- fail-closed skip on missing
ServerID
- accepted with explicit carry-forwards:
localServerID = listenAddrremains transport-shaped for local identity- heartbeat ->
ProcessAssignments()is proven, but not full end-to-end gRPC delivery - integrated catch-up execution is not yet proven through the live path
- rebuild execution remains deferred
CommittedLSN = CheckpointLSNremains unresolved
P2: Execution Closure
- close the live engine -> executor ->
v2bridgeexecution chain - make catch-up execution evidence integrated rather than split across layers
- close the first rebuild execution path required by the product path
Technical focus:
- keep execution ownership explicit:
- engine plans and owns recovery state transitions
- engine executor drives stepwise execution
v2bridgetranslates execution requests into real blockvol workblockvolperforms I/O only
- prove catch-up as one real path:
- accepted control delivery
- real retained-history input
- real WAL retention pin
- real WAL scan / progress return
- real session completion
- choose the narrowest rebuild closure required by the current product path:
- first real
full-baserebuild path is preferred snapshot + tailcan remain later unless needed by the chosen path
- first real
- keep resource ownership fail-closed:
- pin acquisition before execution
- release on success
- release on cancel / invalidation
- release on partial failure
- keep observability causal:
- execution start
- execution progress
- execution cancel / invalidation
- execution failure
- completion
Implementation route:
- reuse engine-side execution core:
sw-block/engine/replication/driver.gosw-block/engine/replication/executor.gosw-block/engine/replication/orchestrator.go
- reuse storage/runtime execution bridge:
weed/storage/blockvol/v2bridge/executor.goweed/storage/blockvol/v2bridge/pinner.goweed/storage/blockvol/v2bridge/reader.go
- reuse block runtime execution reality:
weed/storage/blockvol/blockvol.goweed/storage/blockvol/replica_apply.goweed/storage/blockvol/replica_barrier.go- rebuild-side files under
weed/storage/blockvol/
- preserve the boundary:
- do not move zero-gap / catch-up / rebuild classification into
blockvol - do not let executor convenience paths redefine protocol semantics
- do not move zero-gap / catch-up / rebuild classification into
Validation focus:
- prove one live integrated catch-up chain:
- assignment/control arrives through accepted
P1path - engine plans
- executor drives
v2bridge blockvolexecutes- progress returns
- session completes
- assignment/control arrives through accepted
- prove one real rebuild execution path for the chosen product path
- prove retention pin / release symmetry on the live path
- prove rebuild resource pin / release symmetry on the live path
- prove invalidation / cancel cleanup on the live path
- prove execution logs explain:
- why catch-up started
- why rebuild started
- why execution failed
- why execution was cancelled
- why completion succeeded
Reject if:
- catch-up is still only proven by split evidence
- rebuild remains only a detection outcome
blockvolstarts deciding recovery mode or rebuild fallback- resources leak on cancel / invalidation / partial failure
- execution logs are too weak to replay causality offline
- the slice quietly broadens protocol semantics beyond the current accepted boundary
Recommended first cut:
- close the live catch-up chain first
- close the first real
full-baserebuild path second - leave unified replay to
P3
Minimum closure threshold:
- do not accept
P2on glue code + partial chain tests alone - at least one accepted catch-up proof must drive the real engine executor path:
PlanRecovery(...)NewCatchUpExecutor(...)- executor-managed progress / completion
- real
v2bridge/blockvolexecution underneath
- at least one accepted rebuild proof must drive the real engine executor path:
- rebuild assignment
PlanRebuild(...)NewRebuildExecutor(...)- executor-managed completion
- real
TransferFullBase(...)underneath
- resource-cleanup proof must include live-path assertions, not only logs:
- active holds released
- retention floor no longer pinned after release
- no surviving session/plan ownership after cancel / invalidation / failure
- observability proof should include executor-generated events, not only planner-side events
- if these thresholds are not met, record
P2as partial execution progress, not execution closure
Carry-forward note:
- on the chosen
RF=2 sync_allpath,CommittedLSNseparation is resolved in this slice:CommittedLSN = WALHeadLSNCheckpointLSNremains the durable base-image boundary
- this is not yet a blanket truth for every future path or durability mode
- post-checkpoint catch-up remains bounded unless explicitly closed
- rebuild coverage is limited to the first chosen executable path if that is all that lands
Status:
- accepted
- real one-chain execution is now proven for:
- catch-up
- rebuild
- accepted evidence includes:
CommittedLSNseparated fromCheckpointLSNon the chosensync_allpath- live engine plan -> executor ->
v2bridge->blockvolcatch-up chain - live engine plan -> executor ->
v2bridge->blockvolrebuild chain - explicit pin cleanup assertions after execution
- accepted with explicit residual scope:
CatchUpStartLSNis not directly asserted in tests- rebuild source is not yet forced/verified per source variant
- broader rebuild-source coverage can remain follow-up work
Review checklist:
- is there one accepted catch-up proof from real
P1control path to real session completion, usingCatchUpExecutor - is there one accepted first rebuild proof on the chosen path, using
RebuildExecutor - do live-path assertions prove pin/hold release on success, cancel, invalidation, and failure
- do logs/status explain start, cancel, failure, and completion without hidden transitions
- does the delivery avoid overclaiming general post-checkpoint catch-up, broad rebuild coverage, or production readiness
P3: Hardening Validation
- replay the accepted failure-class set again on the unified live path after
P1+P2 - validate at least one real failover / promotion / reassignment cycle through the live control path
- validate concurrent retention/pinner behavior under overlapping recovery activity
- make the committed-truth gate decision explicit for the chosen candidate path
Slice adjustment note:
- if
P2lands only partially,P3should first close the missing execution outcome:- real catch-up closure if still missing
- real first rebuild closure if still missing
- only after both are real should
P3spend most of its weight on unified replay, failover / reassignment validation, and concurrent retention / cleanup hardening
Efficiency note:
P3is a hardening-validation slice, not another execution-closure slice- reuse the accepted
P1/P2live path as the base; do not re-prove already accepted chain mechanics in isolation - prefer one compact replay matrix over many near-duplicate tests
- prefer one real failover cycle and one true simultaneous-overlap retention case over broad scenario expansion
- the required new outputs are:
- unified replay evidence
- one real failover / reassignment replay
- one concurrent retention/pinner safety result
- one explicit committed-truth gate decision
Validation focus:
- unified replay for:
- changed-address restart
- stale epoch / stale session
- unrecoverable gap / needs-rebuild
- post-checkpoint boundary behavior
- at least one real failover / promotion / reassignment cycle
- concurrent retention/pinner safety under at least one true simultaneous-overlap hold case
- logs explain:
- why control truth changed
- why a session was invalidated
- why catch-up vs rebuild was chosen
- why execution completed, failed, or was cancelled
Reject if:
- accepted failure classes are still only partially replayed on the unified path
- failover / reassignment is claimed without a real live-path replay
- concurrent retention/pinner behavior leaks pins or violates recovery safety
- logs are too weak to replay causality offline
- the committed-truth gate is still just a note instead of an explicit decision
Status:
- accepted
- unified hardening replay is now proven on the accepted live path
- accepted evidence includes:
- replay of the accepted failure-class set on the unified
P1+P2path - at least one real failover / reassignment cycle through the live control path
- one true simultaneous-overlap retention/pinner safety proof
- stronger causality assertions for invalidation, escalation, catch-up, and completion
- replay of the accepted failure-class set on the unified
- committed-truth gate decision for the chosen candidate path:
- for the chosen
RF=2 sync_allcandidate path,CommittedLSN = WALHeadLSNwithCheckpointLSNkept separate is accepted as sufficient for the candidate-path hardening boundary - this is not yet a blanket truth for every future path or durability mode
- for the chosen
P4: Candidate Package Closure
- classify what is truly ready for a first candidate path
- package the accepted
P1/P2/P3evidence into one bounded candidate package - turn carry-forwards into explicit candidate bounds or hard gates
- state clearly what still remains before production readiness
Goal:
- finish
Phase 08with one explicit candidate package, not just a collection of accepted slices
Verification mechanism:
- evidence map:
- every candidate claim must point to accepted evidence from
P1/P2/P3
- every candidate claim must point to accepted evidence from
- tester validation:
- verify each candidate claim is supported by accepted evidence
- reject any claim that exceeds the proven boundary
- manager validation:
- verify the candidate statement is explicit, bounded, and not confused with production readiness
Output artifacts:
- candidate-path statement in
phase-08.md - candidate/gate decision record in
phase-08-decisions.md - concise candidate package summary:
- candidate-safe capabilities
- explicit bounds
- deferred / blocking items
- concise residual-gap summary:
- candidate-safe
- intentionally bounded
- still deferred / still blocking
- short module/package boundary summary for later phases:
- what is already strong enough
- what moves to the next heavy engineering phase
Efficiency note:
P4should mostly consume already accepted evidence, not create broad new engineering work- only add implementation work if a small remaining blocker must be closed to make the candidate statement coherent
- if a gap is real but not worth closing in
Phase 08, classify it explicitly rather than expanding scope implicitly P4exists insidePhase 08so the next phase can begin with substantial engineering work, not a light packaging-only round
Validation focus:
- make the candidate-path boundary explicit:
- what is proven
- what is intentionally bounded
- what is still deferred
- make the candidate package explicit:
- candidate-safe capability list
- evidence-to-claim mapping
- short module/package boundary summary
- make the committed-truth decision explicit:
- accepted for the chosen
RF=2 sync_allcandidate path - still unclassified for future paths / durability modes unless separately proven
- accepted for the chosen
- prove the accepted product path can be described as an engineering candidate, not only as a set of slice-local proofs
- provide one explicit residual-gap list that separates:
- candidate-safe bounds
- future hardening work
- production blockers
Reject if:
P4reopens protocol design instead of closing engineering gaps- candidate claims are broader than the proven path
- carry-forwards remain informal notes rather than bounds or gates
- production readiness is implied from candidate readiness
P4produces only prose summary without an evidence-to-claim mappingP4is too thin to leave the next phase with substantial engineering closure work
Status:
- accepted
- the first candidate package is now explicit for the chosen path
- accepted evidence includes:
- candidate-safe claims mapped to accepted
P1/P2/P3evidence - explicit bounds for
RF=2 sync_all - explicit deferred / blocking items before production use
- committed-truth decision scoped to the chosen candidate path
- short module/package boundary summary for the next heavy engineering phase
- candidate-safe claims mapped to accepted
- accepted judgment:
- candidate-safe-with-bounds
- not production-ready
Guardrails
Guardrail 1: Do not reopen accepted V2 protocol truths casually
Phase 08 is a hardening phase. New work should preserve the accepted protocol truth set unless a real contradiction is demonstrated.
Guardrail 2: Keep product-path claims evidence-bound
Do not claim more than the hardened path actually proves. Distinguish:
- live integrated path
- hardened product path
- production candidate
Guardrail 3: Identity and policy boundaries remain hard rules
ReplicaIDmust remain stable and never collapse to address shape- engine decides recovery policy
- bridge translates intent/state
blockvolexecutes I/O only
Guardrail 4: Carry-forward limitations must remain explicit until closed
Especially:
- committed truth vs checkpoint truth
- rebuild execution coverage
- real master/control delivery coverage
Guardrail 5: The committed-truth carry-forward must become a gate, not a note
For the chosen RF=2 sync_all candidate path, this gate is now decided:
CommittedLSN = WALHeadLSNCheckpointLSNremains the durable base-image boundary- this separation is accepted as sufficient for the candidate-path hardening boundary
For future paths or durability modes, the gate must still be classified explicitly rather than carried forward informally.
Exit Criteria
Phase 08 is done when:
- the first product path runs through a real control delivery path
- the critical execution chain is integrated and validated
- rebuild execution for the chosen path is no longer just detected but executed
- at least one real failover / reassignment cycle is replayed through the live control path
- the accepted failure-class set is replayed again on the unified live path
- operational/debug evidence is sufficient for pre-production use
- the remaining gap to a production candidate is small and explicit
Phase-close note:
Phase 08is now closed- next phase:
Phase 09: Production Execution Closure- start with
P0planning for real execution completeness:- real
TransferFullBase - real
TransferSnapshot - real
TruncateWAL - stronger live runtime execution ownership
- real
Assignment For sw
Current next tasks:
- close out
Phase 08bookkeeping only if any wording drift remains - move to
Phase 09 P0planning for production execution closure - focus the next heavy engineering package on:
- real
TransferFullBase - real
TransferSnapshot - real
TruncateWAL - stronger live runtime execution ownership
- real
Assignment For tester
Current next tasks:
- treat
Phase 08as closed after any final wording/bookkeeping sync - prepare the
Phase 09 P0validation oracle for production execution closure - keep no-overclaim active around:
- validation-grade transfer vs production-grade transfer
- truncation execution
- stronger runtime ownership vs current bounded path