docs: Phase 13 CP13-1..CP13-7 technical packs, acceptance status, design updates

- phase-13.md: CP13-1 through CP13-6 accepted, CP13-7 active
- phase-13-log.md: full technical + delivery packs for CP13-2..CP13-7
- phase-13-cp4-state-eligibility.md: refined barrier behavior table
  (Disconnected/Degraded as recovery entry points, not eligibility)
- phase-12.md: minor cross-reference updates
- Older phase docs: minor wording alignment
- Design docs: V2 development plan and completion overview updated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
pingqiu
2026-04-03 08:48:05 -07:00
co-authored by Claude Opus 4.6
parent 1d3fb1f119
commit 21ccf06ef3
6 changed files with 1793 additions and 48 deletions
+9 -19
View File
@@ -1,7 +1,7 @@
# Phase 12
Date: 2026-04-02
Status: active
Status: accepted
Purpose: move the accepted chosen-path implementation from candidate-safe product closure toward production-safe behavior under restart, disturbance, and operational reality
## Why This Phase Exists
@@ -423,7 +423,7 @@ Reject if:
Status:
- active
- accepted
Carry-forward from `P3`:
@@ -431,23 +431,13 @@ Carry-forward from `P3`:
2. `P4` now asks whether that accepted path has an explicit measured floor and an explicit first-launch envelope
3. later work after `Phase 12` should be a productionization program, not another hidden hardening slice
## Assignment For `sw`
## Phase Close-Out Note
Current next tasks:
`Phase 12` is now accepted as bounded production hardening on the chosen path:
1. deliver `Phase 12 P4` as bounded performance-floor / rollout-gate hardening
2. keep the acceptance object fixed on one measured workload envelope plus one explicit launch-envelope / gate artifact
3. keep earlier accepted `Phase 09` / `Phase 10` / `Phase 11` / `Phase 12 P1` / `Phase 12 P2` / `Phase 12 P3` semantics stable unless `P4` exposes a real bug or measurement-surface gap
4. do not let `P4` turn into broad optimization, topology expansion, or generic launch marketing
1. `P1` accepted disturbance correctness
2. `P2` accepted bounded soak / long-run stability
3. `P3` accepted diagnosability / blocker accounting / runbook hardening
4. `P4` accepted bounded performance floor / rollout-gate hardening
## Assignment For `tester`
Current next tasks:
1. validate `P4` as real bounded performance-floor / rollout-gate hardening rather than “benchmark numbers exist” prose
2. require explicit validation targets for:
- one named workload envelope with measured floor values
- one explicit launch-envelope / rollout-gate artifact
- no-overclaim around broad production readiness beyond the named envelope
3. keep no-overclaim active around accepted `Phase 09` / `Phase 10` / `Phase 11` / `Phase 12 P1` / `Phase 12 P2` / `Phase 12 P3` closure
4. keep `P4` bounded rather than letting it absorb post-Phase-12 productionization work
Next work should open a new phase or program rather than silently continuing inside `Phase 12`.
@@ -7,14 +7,14 @@ Code change: one new test (`TestBarrier_NonEligibleStates_FailClosed`)
The replication path uses a bounded 6-state set (`wal_shipper.go:25-30`):
| State | Value | Meaning | Barrier eligible? |
|-------|-------|---------|-------------------|
| `Disconnected` | 0 | No session (initial state) | No — attempts bootstrap/reconnect, fails if no progress |
| `Connecting` | 1 | Socket open, handshake pending | No — immediate `ErrReplicaDegraded` |
| `CatchingUp` | 2 | Connected, replaying missed WAL | No — immediate `ErrReplicaDegraded` |
| `InSync` | 3 | Eligible for sync_all barriers | **Yes** — only state that proceeds to barrier request |
| `Degraded` | 4 | Transient failure, retry allowed | No — attempts reconnect, fails if reconnect fails |
| `NeedsRebuild` | 5 | WAL gap too large, rebuild required | No — immediate `ErrReplicaDegraded` |
| State | Value | Meaning | Barrier behavior |
|-------|-------|---------|-----------------|
| `Disconnected` | 0 | No session (initial state) | Attempts bootstrap/reconnect inside Barrier(); fails if no progress or reconnect fails |
| `Connecting` | 1 | Socket open, handshake pending | Immediate `ErrReplicaDegraded` |
| `CatchingUp` | 2 | Connected, replaying missed WAL | Immediate `ErrReplicaDegraded` |
| `InSync` | 3 | Eligible for sync_all barriers | **Proceeds to barrier request** — only state that can complete barrier successfully |
| `Degraded` | 4 | Transient failure, retry allowed | Attempts reconnect inside Barrier(); fails if reconnect fails |
| `NeedsRebuild` | 5 | WAL gap too large, rebuild required | Immediate `ErrReplicaDegraded` |
## Barrier State Gate
@@ -33,16 +33,28 @@ default:
}
```
**Only `InSync` enters the barrier request path.** All other states either fail immediately or attempt reconnect (which must succeed and transition to `InSync` before reaching the barrier).
**Contract (precise):**
- **Only `InSync` can complete barrier successfully.** It is the only state that proceeds
directly to the barrier request (ensureCtrlConn → MsgBarrierReq → wait for BarrierOK).
- **`Disconnected` and `Degraded` use Barrier() as a recovery entry point.** They attempt
bootstrap/reconnect inside the Barrier() call. If recovery succeeds and transitions to
InSync, the barrier request proceeds. If recovery fails, the barrier fails.
- **`Connecting`, `CatchingUp`, `NeedsRebuild` are rejected immediately** with `ErrReplicaDegraded`.
The key distinction: Barrier() can be *invoked* from Disconnected/Degraded (as a recovery
trigger), but only InSync can *satisfy* barrier success. The Disconnected/Degraded paths
are recovery attempts, not barrier eligibility.
## sync_all Gate
`dist_group_commit.go:59-66`: sync_all counts barrier failures. Any shipper that returns an error from `Barrier()` increments `failCount`. If `failCount > 0`, sync_all returns `ErrDurabilityBarrierFailed`.
Combined with the CP13-3 fix (FlushedLSN=0 rejected), the full chain is:
1. Only `InSync` shippers reach the barrier request
2. Only `BarrierOK` with `FlushedLSN > 0` counts as success
3. sync_all fails if any barrier fails
1. Only `InSync` shippers proceed to the barrier request
2. Disconnected/Degraded may recover inside Barrier(), transitioning to InSync before requesting
3. Only `BarrierOK` with `FlushedLSN > 0` counts as success
4. sync_all fails if any barrier fails
## Proof Promotion
@@ -50,7 +62,7 @@ Combined with the CP13-3 fix (FlushedLSN=0 rejected), the full chain is:
| Test | What it proves for CP13-4 |
|------|--------------------------|
| `TestBarrier_NonEligibleStates_FailClosed` | Connecting, CatchingUp, NeedsRebuild all rejected immediately; Disconnected fails on dead address; only InSync enters barrier path |
| `TestBarrier_NonEligibleStates_FailClosed` | 5 sub-cases: Connecting/CatchingUp/NeedsRebuild rejected immediately; Disconnected fails (no recovery on dead addr); InSync enters barrier path (verified by MsgBarrierReq receipt on fake server) |
| `TestBarrier_RejectsReplicaNotInSync` | SyncCache fails when replica is not InSync (end-to-end) |
| `TestBarrier_DuringCatchup_Rejected` | Barrier rejected while replica is CatchingUp |
| `TestDistSync_SyncAll_AllDegraded_Fails` | sync_all fails when all replicas degraded |
File diff suppressed because it is too large Load Diff
+608
View File
@@ -0,0 +1,608 @@
# Phase 13
Date: 2026-04-02
Status: active
Purpose: carry one explicit engineering gap beyond accepted `Phase 12` hardening into a bounded implementation phase so `RF=2 sync_all` becomes a correct, test-backed replicated durability mode under real reconnect, catch-up, retention, and rebuild conditions
## Why This Phase Exists
`Phase 09` accepted chosen-path execution closure.
`Phase 10` accepted bounded control-plane closure.
`Phase 11` accepted bounded product-surface rebinding.
`Phase 12` accepted bounded hardening, diagnosability, and first-launch envelope evidence.
What still remains is not broad protocol discovery.
It is one concrete engineering problem:
1. `sync_all` still needs a cleaner replicated-durability contract under cross-machine reconnect and replica recovery reality
2. that contract must be expressed in code and tests so later feature work can reuse it rather than reopen replication semantics repeatedly
## Phase Goal
Turn `RF=2 sync_all` from a bounded chosen-path mode with accepted launch-hardening evidence into a correct, reusable replicated-durability model for reconnect, catch-up, retention, and rebuild on real workloads.
Execution note:
1. use `phase-13-log.md` as the technical pack for:
- checkpoint breakdown
- acceptance objects
- reject shapes
- assignment text for `sw` and `tester`
2. prefer test-first baseline plus checkpointed implementation
3. keep the goal narrow: replication correctness first, not broad optimization or new transport work
## Scope
### In scope
1. canonical replica address truth
2. authoritative per-replica durable-progress tracking
3. reconnect handshake and WAL catch-up
4. replica-aware WAL retention / truncation
5. rebuild fallback when catch-up is impossible
6. real ext4 / PostgreSQL validation on real block devices for cross-machine `sync_all`
7. mode normalization work that depends directly on the corrected replication model
### Out of scope
1. broad new protocol discovery outside the replication path
2. new transport projects such as `SPDK`, `io_uring`, or striped-layout redesign
3. generic benchmark positioning beyond correctness-backed validation
4. unrelated control-plane or product-surface expansion
5. reopening accepted `Phase 09` / `Phase 10` / `Phase 11` / `Phase 12` semantics unless this phase exposes a real bug
## Phase 13 Items
### `CP13-1`: Test-First Baseline
Goal:
- freeze a failing/passing baseline that exposes the current replication gaps before protocol work begins
Acceptance object:
1. the focused sync-replication gap tests exist
2. they are run on current code before major implementation work
3. the fail/pass split is captured explicitly so later checkpoint claims are grounded
Status:
- accepted
Carry-forward:
1. the baseline report is frozen in `phase-13-cp1-baseline.md`
2. no protocol code was changed in `CP13-1`
3. `CP13-2` and later checkpoints must treat the baseline as the starting truth, not redefine it after implementation
### `CP13-2`: Canonical Replica Addressing
Goal:
- make replica endpoint truth canonical and routable so cross-machine replication never depends on wildcard listener strings, incomplete `:port` forms, or other non-authoritative address leakage
Acceptance object:
1. `CP13-2` accepts canonical replica address truth for the replication path
2. it does not accept durable-progress truth, reconnect protocol, WAL retention, or rebuild fallback by implication
3. it does not accept broad networking redesign beyond endpoint canonicalization
Execution steps:
1. Step 1: address truth contract freeze
- define the canonical replica endpoint form for replication surfaces as routable `host:port`
- define which forms are invalid for exported/registered truth:
- bare `:port`
- wildcard listener strings such as `[::]:port`
- accidental loopback when cross-machine routing is intended
2. Step 2: implementation hardening
- canonicalize replica listener addresses at the source where receiver/registration surfaces expose them
- keep authoritative endpoint truth aligned across local listener state, registration/heartbeat publication, and any registry copies
3. Step 3: proof package
- prove canonical `host:port` truth is emitted under wildcard-bind cases
- prove no wildcard or incomplete address string leaks into exported replication truth
- prove no-overclaim around reconnect, retention, or rebuild semantics
Required scope:
1. replica receiver endpoint truth
2. registration / heartbeat / registry path carrying replica endpoints
3. one focused wildcard-bind proof plus bounded cross-machine truth checks
4. explicit distinction between address canonicalization and later reconnect protocol work
Must prove:
1. cross-machine replica addresses exported for replication are canonical routable `host:port`
2. wildcard bind strings do not escape into replication truth
3. local canonicalization does not silently rewrite intentionally loopback-only cases into incorrect external truth
4. acceptance wording stays bounded to endpoint truth rather than later replication recovery semantics
Reuse discipline:
1. `weed/storage/blockvol/replica_receiver.go`, `replica_meta.go`, and nearby address helpers may be updated in place as the primary endpoint-truth surface
2. `weed/server/master_block_registry.go` and heartbeat/registration paths may be updated in place only if needed to keep authoritative endpoint truth aligned
3. focused unit/protocol tests should carry the main proof burden; component tests are support-only unless they prove an otherwise unreachable leak
4. no checkpoint work may silently introduce reconnect protocol, retention policy, or rebuild logic
Verification mechanism:
1. one focused wildcard-bind canonicalization proof
2. explicit checks that exported/registered replica endpoints are routable `host:port`
3. no-overclaim review so `CP13-2` does not absorb `CP13-3+`
Hard indicators:
1. one accepted canonical-endpoint proof:
- wildcard-bind listener state resolves to canonical exported `host:port`
2. one accepted no-leak proof:
- bare `:port` / wildcard listener strings no longer escape into replication truth
3. one accepted boundedness proof:
- `CP13-2` claims endpoint truth only, not reconnect or durability semantics
Reject if:
1. the checkpoint fixes only one test string shape but leaves other exported endpoint paths unchanged
2. canonicalization happens only in tests rather than at the production truth surface
3. the checkpoint quietly broadens into reconnect, retention, or rebuild protocol work
Status:
- accepted
Carry-forward:
1. `localServerID` remains stable control identity and may be opaque
2. `advertisedHost` is now the transport-facing canonicalization input for wildcard-bind replica endpoints
3. `CP13-3` and later checkpoints must not reopen identity-vs-transport separation unless a new concrete bug is exposed
### `CP13-3`: Durable Progress Truth
Goal:
- make durable replication progress explicit and authoritative so sync correctness is grounded in replica flushed durability rather than sender-side send progress or loosely inferred health
Acceptance object:
1. `CP13-3` accepts durable progress truth for the replication path
2. it does not accept reconnect/catch-up protocol, retention policy, rebuild fallback, or broader state-machine closure by implication
3. it does not accept generic “tests pass” reasoning without an explicit durable-progress contract review
Execution steps:
1. Step 1: durable-progress contract freeze
- define `replicaFlushedLSN` as replica-side WAL durability confirmed at barrier time
- define sender-side shipped/sent progress as diagnostic only, not authority for sync correctness
- define what barrier responses must expose as explicit durable progress truth
2. Step 2: implementation hardening or proof confirmation
- update the durable-progress path only where current code fails to meet the contract
- if current code already satisfies the contract, keep changes minimal and make the proof package explicit instead of broadening scope
3. Step 3: proof package
- prove barrier success is grounded in replica flushed durability
- prove flushed progress is monotonic within epoch and not updated on mere receive
- prove no-overclaim around `CP13-4+`
Required scope:
1. replica receiver durable-progress state
2. barrier request/response path
3. sender/group tracking of replica durable progress
4. explicit separation between durable-progress truth and later reconnect / retention semantics
Must prove:
1. `replicaFlushedLSN` means replica durability, not sender transmission progress
2. barrier responses expose durable progress explicitly enough for sync correctness decisions
3. sender-side progress such as shipped/sent LSN is diagnostic only and cannot authorize sync success
4. acceptance wording stays bounded to durable-progress truth rather than broader recovery/state-machine closure
Reuse discipline:
1. `weed/storage/blockvol/replica_apply.go`, `wal_shipper.go`, `dist_group_commit.go`, and related protocol message code may be updated in place as the primary durable-progress surfaces
2. focused unit/protocol tests should carry the main proof burden
3. `weed/server/*` should remain reference only unless durable-progress truth requires an exposed wiring change
4. no checkpoint work may silently introduce reconnect protocol, retention policy, rebuild policy, or broader transport redesign
Verification mechanism:
1. one focused proof set around barrier/flushed progress truth
2. explicit checks that receive progress alone does not advance durable authority
3. no-overclaim review so `CP13-3` does not absorb `CP13-4+`
Hard indicators:
1. one accepted barrier-truth proof:
- barrier success is tied to replica flushed durability
2. one accepted monotonicity proof:
- `replicaFlushedLSN` is monotonic within epoch
3. one accepted no-false-authority proof:
- sender-side shipped/sent progress is diagnostic only
4. one accepted boundedness proof:
- `CP13-3` claims durable-progress truth only
Reject if:
1. the checkpoint treats passing baseline tests as automatic closure without reviewing the durable-progress contract
2. durable-progress truth is still mixed with sender-side transmission progress
3. the checkpoint quietly broadens into reconnect, retention, rebuild, or general replication redesign
Status:
- accepted
Carry-forward:
1. `replicaFlushedLSN` is now the authoritative durable-progress variable for `sync_all`
2. legacy `BarrierOK` responses without `FlushedLSN` are rejected and cannot count as durable authority
3. `CP13-4` and later checkpoints must treat sender-side send progress as diagnostic only, not as sync-correctness authority
### `CP13-4`: Replica State Machine / Barrier Eligibility
Goal:
- make replica state and barrier eligibility explicit so only `InSync` replicas can satisfy sync durability while non-eligible states fail closed instead of drifting into accidental success
Acceptance object:
1. `CP13-4` accepts the replica state machine and barrier-eligibility contract
2. it does not accept reconnect/catch-up protocol, retention policy, rebuild fallback, or broader rollout claims by implication
3. it does not accept vague “state seems fine” reasoning without an explicit eligibility contract
Execution steps:
1. Step 1: state contract freeze
- define the bounded state set used by the replication path:
- `Disconnected`
- `Connecting`
- `CatchingUp`
- `InSync`
- `Degraded`
- `NeedsRebuild`
- define barrier eligibility:
- only `InSync` replicas count toward sync durability
- non-eligible states must pre-reject or fail closed
2. Step 2: implementation hardening or proof confirmation
- update the state/eligibility path only where current code fails the contract
- if current code already satisfies much of the contract, keep code changes minimal and make the proof package explicit
3. Step 3: proof package
- prove barrier rejects replicas not eligible for sync durability
- prove degraded or catching-up replicas do not silently count toward `sync_all`
- prove no-overclaim around `CP13-5+`
Required scope:
1. replica shipper state transitions and eligibility checks
2. barrier admission path
3. `sync_all` failure semantics when replicas are non-eligible
4. explicit separation between state eligibility and later reconnect/rebuild protocol work
Must prove:
1. only `InSync` replicas count toward sync durability
2. `Disconnected`, `Connecting`, `CatchingUp`, `Degraded`, and `NeedsRebuild` do not silently satisfy barrier eligibility
3. degraded/non-eligible replicas fail closed for `sync_all` rather than producing false durability success
4. acceptance wording stays bounded to state/eligibility truth rather than reconnect, retention, or rebuild closure
Reuse discipline:
1. `weed/storage/blockvol/wal_shipper.go`, `dist_group_commit.go`, `shipper_group.go`, and nearby replication coordination code may be updated in place as the primary state/eligibility surfaces
2. focused unit/protocol/adversarial tests should carry the main proof burden
3. `weed/server/*` should remain reference only unless state eligibility requires a surfaced wiring correction
4. no checkpoint work may silently introduce reconnect handshake, retention policy, rebuild flow, or broader transport redesign
Verification mechanism:
1. one focused proof set around replica state and barrier eligibility
2. explicit checks that non-`InSync` states cannot satisfy `sync_all`
3. no-overclaim review so `CP13-4` does not absorb `CP13-5+`
Hard indicators:
1. one accepted eligibility proof:
- only `InSync` replicas count toward sync durability
2. one accepted fail-closed proof:
- non-eligible replicas cause bounded failure rather than false success
3. one accepted state-boundary proof:
- barrier rejects or excludes disallowed states explicitly
4. one accepted boundedness proof:
- `CP13-4` claims state/eligibility truth only
Reject if:
1. the checkpoint treats passing baseline tests as automatic closure without restating the state/eligibility contract
2. non-eligible replica states can still satisfy sync durability
3. the checkpoint quietly broadens into reconnect, retention, rebuild, or general replication redesign
Status:
- accepted
Carry-forward:
1. the replica state set and barrier-eligibility contract are now explicit
2. only `InSync` may satisfy sync durability; `Disconnected`/`Degraded` may invoke `Barrier()` only as bounded recovery entry paths
3. `CP13-5` and later checkpoints must preserve this eligibility boundary rather than reopening it implicitly
### `CP13-5`: Reconnect Handshake + WAL Catch-up
Goal:
- make reconnect after replica disturbance explicit and correct so a replica with known durable progress can resume from retained WAL, catch up, and re-enter `InSync` without false bootstrap success or barrier hangs
Acceptance object:
1. `CP13-5` accepts the reconnect handshake and WAL catch-up contract for recoverable gaps on the replication path
2. it does not accept replica-aware WAL retention policy, full rebuild fallback lifecycle, or broader rollout claims by implication
3. it does not accept vague “reconnect seems to work” reasoning without an explicit resume/catch-up contract
Execution steps:
1. Step 1: reconnect contract freeze
- define when a replica must use bootstrap versus reconnect:
- fresh replica with no prior durable progress may bootstrap
- replica with prior flushed progress must reconnect via explicit resume truth
- define reconnect decision outcomes:
- already caught up
- recoverable gap within retained WAL
- unrecoverable gap that must fail closed and defer full rebuild handling to `CP13-7`
2. Step 2: implementation hardening
- update the reconnect path only where current code still fails the resume/catch-up contract
- ensure catch-up replays retained WAL before barrier success is allowed
- ensure repeated disconnect/reconnect cycles remain bounded and do not silently fall back to unsafe bootstrap
3. Step 3: proof package
- prove degraded replicas with prior durable progress use handshake/reconnect rather than bootstrap
- prove retained-WAL catch-up completes and re-enters `InSync` on recoverable gaps
- prove reconnect fails closed on unrecoverable or incomplete recovery cases
- prove no-overclaim around `CP13-6+`
Required scope:
1. `wal_shipper` reconnect discriminator and resume handshake
2. retained-WAL catch-up replay path
3. repeated disconnect/reconnect recovery behavior
4. bounded failure semantics for gaps that cannot be recovered within this checkpoint
5. explicit separation between reconnect/catch-up closure and later retention/rebuild policy work
Must prove:
1. fresh shippers bootstrap, but previously-synced shippers reconnect using resume truth
2. barrier success after disturbance is allowed only after reconnect/catch-up has re-established `InSync`
3. repeated disconnect/reconnect cycles do not strand the replica in false degraded recovery
4. recoverable gaps replay retained WAL correctly without overwriting newer replica data
5. acceptance wording stays bounded to reconnect/catch-up truth rather than retention or rebuild closure
Reuse discipline:
1. `weed/storage/blockvol/wal_shipper.go`, reconnect/catch-up helpers, and nearby replication protocol code may be updated in place as the primary reconnect surface
2. focused protocol/adversarial tests should carry the main proof burden; component tests are support-only unless a protocol gap is otherwise unreachable
3. `weed/server/*` should remain reference only unless reconnect correctness requires surfaced wiring changes
4. no checkpoint work may silently broaden into retention policy, rebuild orchestration, or performance tuning
Verification mechanism:
1. one focused proof set around reconnect discriminator, catch-up replay, and post-reconnect barrier behavior
2. explicit checks for repeated disconnect/reconnect recovery
3. explicit checks that recoverable gaps replay retained WAL before sync success
4. no-overclaim review so `CP13-5` does not absorb `CP13-6+`
Hard indicators:
1. one accepted reconnect-discriminator proof:
- prior durable progress uses handshake/reconnect rather than bootstrap
2. one accepted catch-up proof:
- recoverable retained-WAL gap replays and returns to `InSync`
3. one accepted repeated-recovery proof:
- multiple disconnect/reconnect cycles recover without hanging or drifting
4. one accepted fail-closed proof:
- reconnect does not falsely succeed when recovery is incomplete or impossible within retained WAL
5. one accepted boundedness proof:
- `CP13-5` claims reconnect/catch-up truth only
Reject if:
1. a previously-synced replica can still skip resume truth and succeed via unsafe bootstrap
2. barrier success can occur before reconnect/catch-up has restored `InSync`
3. repeated reconnect cycles still hang, strand, or silently degrade correctness
4. the checkpoint quietly broadens into retention, explicit `NeedsRebuild` lifecycle closure, rebuild execution, or general replication redesign
Status:
- accepted
Carry-forward:
1. replacement shippers now preserve prior durable-progress intent across `SetReplicaAddrs`
2. previously-synced replicas must reconnect through resume truth and retained-WAL catch-up rather than unsafe bootstrap
3. `CP13-6` and later checkpoints must preserve the reconnect/catch-up contract rather than weakening it through reclaim or rebuild shortcuts
### `CP13-6`: Replica-Aware WAL Retention
Goal:
- make WAL retention explicit and replica-aware so reclaim is gated by recoverable replica progress and bounded retention budgets rather than silently discarding catch-up-critical WAL
Acceptance object:
1. `CP13-6` accepts replica-aware WAL retention and retention-budget truth on the replication path
2. it does not accept full rebuild fallback lifecycle, rebuild execution, or broader rollout claims by implication
3. it does not accept vague “reclaim seems safe” reasoning without an explicit retention contract
Execution steps:
1. Step 1: retention contract freeze
- define which replica progress is authoritative for WAL retention:
- only replicas with prior durable progress and still recoverable state may hold WAL
- define bounded retention outcomes:
- reclaim blocked while a recoverable replica still needs retained WAL
- timeout / max-bytes budgets may escalate boundedly and release the WAL hold
- full rebuild handling after escalation remains `CP13-7`
2. Step 2: implementation hardening
- update the retention path only where current code still fails the bounded retention contract
- ensure retention decisions use replica-aware progress rather than primary-local heuristics alone
- ensure budget-triggered escalation is explicit and fail-closed rather than silent reclaim
3. Step 3: proof package
- prove recoverable replicas block reclaim of needed WAL
- prove timeout / max-bytes budgets trigger bounded escalation instead of indefinite WAL growth
- prove retention remains aligned with `CP13-5` reconnect/catch-up truth
- prove no-overclaim around `CP13-7+`
Required scope:
1. WAL retention/reclaim gates
2. shipper-group retention inputs derived from recoverable replica progress
3. bounded timeout / max-bytes escalation behavior
4. explicit separation between retention truth and full rebuild lifecycle closure
Must prove:
1. reclaim does not drop WAL still required by a recoverable replica
2. retention inputs come from replica-aware durable progress, not sender-side guesses
3. timeout / max-bytes budgets trigger bounded escalation when WAL cannot be held indefinitely
4. acceptance wording stays bounded to retention truth rather than full rebuild closure
Reuse discipline:
1. `weed/storage/blockvol` WAL-retention, flusher, shipper-group, and adjacent replication coordination code may be updated in place as the primary retention surface
2. focused unit/protocol tests should carry the main proof burden; component tests are support-only unless a retention gap is otherwise unreachable
3. `weed/server/*` should remain reference only unless retention truth requires surfaced reporting changes
4. no checkpoint work may silently broaden into rebuild execution, broad control-plane redesign, or performance tuning
Verification mechanism:
1. one focused proof set around retention hold, reclaim gating, and budget-triggered escalation
2. explicit checks that max-bytes and timeout paths are real production behaviors, not just comments/logs
3. explicit checks that retention stays compatible with `CP13-5` recoverable catch-up
4. no-overclaim review so `CP13-6` does not absorb `CP13-7+`
Hard indicators:
1. one accepted hold-back proof:
- recoverable replicas block reclaim of required WAL
2. one accepted timeout-budget proof:
- timeout can escalate a stalled recoverable replica into bounded fail-closed behavior
3. one accepted max-bytes-budget proof:
- max-bytes pressure triggers explicit bounded escalation rather than silent reclaim or TODO-only behavior
4. one accepted boundedness proof:
- `CP13-6` claims retention truth only
Reject if:
1. reclaim can still silently discard WAL needed for a recoverable replica
2. max-bytes behavior is still only log text / placeholder behavior without real state effect
3. the checkpoint quietly broadens into full `NeedsRebuild` lifecycle closure, rebuild execution, or general replication redesign
Status:
- accepted
Carry-forward:
1. retention inputs and bounded retention budgets are now replica-aware
2. timeout and max-bytes escalation can move a stalled recoverable replica into `NeedsRebuild`
3. `CP13-7` must turn that escalation into a real fail-closed rebuild lifecycle rather than leaving `NeedsRebuild` as a partially-signaled state
### `CP13-7`: Rebuild Fallback
Goal:
- make `NeedsRebuild` a real fail-closed recovery state so unrecoverable replicas stop participating in normal replication paths, surface rebuild intent clearly, and re-enter the replication contract only through bounded rebuild handoff
Acceptance object:
1. `CP13-7` accepts the `NeedsRebuild` fallback and bounded rebuild handoff lifecycle on the replication path
2. it does not accept broad rollout claims or real-workload validation by implication
3. it does not accept vague “rebuild eventually works” reasoning without an explicit fail-closed lifecycle contract
Execution steps:
1. Step 1: rebuild-fallback contract freeze
- define what `NeedsRebuild` means:
- unrecoverable via retained WAL catch-up
- excluded from normal ship/barrier success
- visible to rebuild orchestration and observability surfaces
- define lifecycle boundaries:
- detection/escalation into `NeedsRebuild`
- fail-closed behavior while in `NeedsRebuild`
- bounded rebuild handoff and post-rebuild re-entry
2. Step 2: implementation hardening
- update the rebuild-fallback path only where current code still leaves `NeedsRebuild` partial, leaky, or inconsistent
- ensure ship/barrier paths block correctly while `NeedsRebuild`
- ensure successful rebuild resets progress/state in a way compatible with later re-entry
3. Step 3: proof package
- prove unrecoverable gaps transition to `NeedsRebuild`
- prove `NeedsRebuild` blocks normal replication participation
- prove rebuild handoff can re-establish a bounded healthy starting point
- prove no-overclaim around `CP13-8+`
Required scope:
1. `NeedsRebuild` detection and state ownership on the primary shipper side
2. fail-closed behavior for ship/barrier and related replication paths while `NeedsRebuild`
3. rebuild start/abort/complete handoff boundaries
4. post-rebuild progress/state initialization needed for safe re-entry
5. explicit separation between rebuild fallback closure and later real-workload validation
Must prove:
1. unrecoverable gaps do not remain merely degraded; they transition to `NeedsRebuild`
2. a shipper in `NeedsRebuild` cannot silently participate in ship/barrier success
3. rebuild completion restores a bounded re-entry point without faking immediate `InSync`
4. acceptance wording stays bounded to rebuild fallback truth rather than `CP13-8` rollout/workload claims
Reuse discipline:
1. `weed/storage/blockvol` rebuild, shipper-group, wal-shipper, and adjacent replication coordination code may be updated in place as the primary rebuild-fallback surface
2. focused unit/protocol/adversarial tests should carry the main proof burden; component tests are support-only unless a rebuild gap is otherwise unreachable
3. `weed/server/*` should remain reference only unless rebuild fallback requires surfaced status/reporting changes
4. no checkpoint work may silently broaden into real-workload benchmarking, performance tuning, or new protocol discovery
Verification mechanism:
1. one focused proof set around `NeedsRebuild` transition, blocking semantics, and rebuild re-entry
2. explicit checks that `NeedsRebuild` blocks normal replication paths rather than merely logging/marking degraded
3. explicit checks that post-rebuild progress initializes from bounded truth such as checkpoint state
4. no-overclaim review so `CP13-7` does not absorb `CP13-8+`
Hard indicators:
1. one accepted transition proof:
- unrecoverable retained-WAL gap transitions to `NeedsRebuild`
2. one accepted fail-closed proof:
- `NeedsRebuild` blocks ship/barrier participation
3. one accepted rebuild-handoff proof:
- rebuild start/complete path restores a bounded re-entry state
4. one accepted post-rebuild-progress proof:
- replica progress after rebuild is initialized from checkpoint truth, not stale/zeroed state
5. one accepted boundedness proof:
- `CP13-7` claims rebuild fallback only
Reject if:
1. an unrecoverable gap can still linger in `Degraded` without escalating to `NeedsRebuild`
2. a `NeedsRebuild` shipper can still satisfy normal ship/barrier paths
3. rebuild completion jumps directly to misleading healthy semantics without bounded re-entry proof
4. the checkpoint quietly broadens into `CP13-8` real-workload validation or general replication redesign
Status:
- active
### Later checkpoints inside `Phase 13`
1. `CP13-8`: real-workload validation
2. `CP13-9`: mode normalization
## Reuse Discipline
1. `weed/storage/blockvol/*` is the primary implementation surface and may be updated in place
2. focused unit/component/adversarial tests should carry the main proof burden
3. real-node / real-device validation belongs in testrunner or bounded component scenarios, not chat prose
4. `weed/server/*` may be updated only when replication correctness requires registry / assignment / heartbeat truth to change
5. no checkpoint may silently broaden into performance-optimization or broad rollout work
## Expected Outcome
If `Phase 13` succeeds:
1. reconnect / catch-up / rebuild semantics become explicit and test-backed
2. `sync_all` correctness no longer depends on partial or implicit sender-state assumptions
3. later feature work can reuse a clearer replication contract instead of re-deriving durability semantics each time
+65 -3
View File
@@ -301,6 +301,60 @@ After `Phase 12`:
3. run a limited internal pilot with incident-driven hardening
4. perform controlled rollout only after explicit launch-gate review
### Post-`Phase 12`: Productionization Program
Goal:
1. turn the accepted `Phase 12` chosen path into a bounded first-launch product envelope without reopening protocol discovery
Program slices:
1. Program `P0`: launch-envelope freeze
- freeze the first supported launch envelope from accepted `P1`-`P4` evidence
- lock:
- supported topology / transport matrix
- explicit exclusions
- launch-blocking vs post-launch blockers
- reject if any launch claim outruns the measured matrix or accepted blockers/gates
2. Program `P1`: internal pilot pack
- convert the frozen launch envelope into a limited internal pilot package
- define:
- pilot environment and topology
- preflight checklist
- success criteria
- stop / rollback conditions
- incident intake template tied to accepted diagnosability surfaces
- reject if pilot success depends on tribal knowledge or undefined operator judgment
3. Program `P2`: incident-driven hardening loop
- route pilot findings into explicit buckets:
- config / environment issue
- known exclusion
- true product bug
- keep one bounded incident ledger and one bounded fix queue
- reject if incidents accumulate as vague notes or exclusions are silently redefined
4. Program `P3`: controlled rollout review
- decide whether to:
- stay in pilot
- widen within the same launch envelope
- block expansion
- require explicit mapping from any expansion decision back to:
- accepted `Phase 12` evidence
- pilot outcomes
- incident dispositions
- reject if rollout broadens beyond the named envelope or reuses pilot success as generic production proof
Cross-cutting rules:
1. do not invent a `Phase 12 P5`; this is a separate productionization program
2. keep the accepted chosen path fixed unless incidents expose a real bug
3. treat known missing evidence as explicit constraints until cleared, especially:
- failover-under-load performance
- hours/days soak under load
- `RF>2`
- broad transport matrix
- full gRPC-stream integration evidence
4. keep V2 post-`Phase 12` direction aligned with the learn-tree close/gate work so the roadmap does not split into contradictory stories
## Module Status Map
@@ -347,18 +401,26 @@ If the goal is to maximize product completion efficiently, the recommended order
2. keep `Phase 10` closed and do not reopen accepted bounded control-plane closure casually
3. move next to `Phase 11` product surface rebinding
4. then `Phase 12` production hardening
5. then the post-`Phase 12` productionization program:
- freeze launch envelope
- run limited internal pilot
- harden from incidents
- review controlled rollout
The most important near-term engineering weight should now go to `Phase 12`.
The most important near-term engineering weight should now go to:
1. finishing `Phase 12`
2. then the bounded productionization program immediately after it
## Short Summary
The V2 line now has accepted execution closure on one bounded chosen path.
The next development plan should treat later work as control/product completion phases, not more protocol discovery.
The next development plan should treat later work as bounded hardening plus productionization, not more protocol discovery.
The main heavy engineering work still ahead is:
1. stronger end-to-end control-plane closure
2. later product-surface rebinding
3. production hardening
4. bounded cleanup of residual operational rough edges without reopening accepted semantics
4. post-`Phase 12` launch-envelope freeze, internal pilot, and controlled rollout review
@@ -228,7 +228,7 @@ Target:
Status:
1. next active stage
1. accepted and closed on the bounded chosen path
Main work:
@@ -237,6 +237,37 @@ Main work:
3. performance floor and cost characterization
4. explicit production blockers / rollout gates
### Stage 6: Post-`Phase 12` Productionization Program
Target:
1. turn the accepted `Phase 12` chosen path into a bounded first-launch product envelope without reopening protocol discovery
Status:
1. next active stage after `Phase 12`
Main work:
1. freeze the first supported launch envelope from accepted `P1`-`P4` evidence
2. define a limited internal pilot package with explicit preflight, success, and stop conditions
3. run incident-driven hardening with explicit classification:
- config / environment issue
- known exclusion
- true product bug
4. perform controlled rollout review only within the named supported envelope
Rules:
1. this is not `Phase 12 P5`
2. pilot success is not generic production proof
3. missing evidence remains an explicit launch constraint until cleared, especially:
- failover-under-load performance
- hours/days soak under load
- `RF>2`
- broad transport matrix
- full gRPC-stream integration evidence
## Completion Gates
The most important gates from here are:
@@ -251,31 +282,35 @@ The most important gates from here are:
- front-end surfaces should only rebind after backend correctness is strong enough
5. production-hardening gate
- restart, soak, diagnosis, and repeated disturbance must be acceptable
6. productionization gate
- first launch envelope, pilot discipline, incident routing, and controlled rollout review must be explicit
## Near-Term Planning Guidance
If the goal is to maximize product completion efficiently:
1. do not make `CSI`, `NVMe`, or broad snapshot productization the immediate next heavy phase
2. first close production execution gaps in the backend path
3. then strengthen control-plane closure
4. then rebind product surfaces
1. do not reopen accepted execution, control-plane, or product-surface semantics casually
2. finish `Phase 12` hardening cleanly
3. then freeze the first supported launch envelope
4. then run a limited internal pilot
5. then widen only through explicit incident review and rollout-gate review
In short:
1. backend truth and execution first
2. product surfaces second
3. production hardening last
1. chosen-path closure first
2. production hardening second
3. bounded productionization third
## Short Summary
The V2 line is already beyond "algorithm only".
It has an accepted bounded chosen path through backend, control-plane, and selected product surfaces.
It has an accepted bounded chosen path through backend, control-plane, selected product surfaces, and `Phase 12` hardening.
But the remaining work is still substantial, and it is mostly engineering work:
1. production hardening under restart / disturbance
2. long-run stability and diagnosability
3. performance floor and rollout gating
1. freeze the first supported launch envelope from accepted evidence
2. run a limited internal pilot with explicit stop conditions
3. harden from incidents without silently broadening scope
4. perform controlled rollout review inside a bounded launch envelope
That is the practical path from the current candidate-safe engine to a production-ready block product.
That is the practical path from the current production-safe chosen path to a bounded first-launch block product.