---
title: "SRBC Core Patch v0.9：Crash-Consistent QRSRC、WAL Ordering 與 Snapshot Lineage"
version: "v0.9"
date: "2026-09-23"
status: "Round 09 crash-consistency patch candidate"
---

# SRBC Core Patch v0.9

Round 09 將 Round 08 的 in-memory atomic recompute 推進到 crash / restart persistence。

核心要求不只是：

$$
S_{t+1}^{\mathrm{inc}}
=
S_{t+1}^{\mathrm{full}}.
$$

還必須保證任意 crash cut 後，對外可見狀態只能是：

$$
\boxed{
S_t
\quad\text{或}\quad
S_{t+1},
}
$$

不得存在：

$$
\boxed{
S_{t+\frac12}.
}
$$

---

# 1. Persistent Transaction State

定義 closure transaction：

$$
T
=
(
\mathrm{txid},
E_p,
H_p,
\mu,
E_c,
H_c
),
$$

其中：

- $E_p$：parent epoch；
- $H_p$：parent manifest hash；
- $\mu$：mutation event；
- $E_c=E_p+1$：child epoch；
- $H_c$：child manifest hash。

---

# 2. Durable WAL Order

v0.9 建議第一代 durable order：

```text
BEGIN
  ↓ fsync
EVENT
  ↓ fsync
PREPARE
  ↓
IMMUTABLE CHILD SNAPSHOT BLOB
  ↓ fsync
COMMIT
  ↓ fsync
ATOMIC HEAD ADVANCE
  ↓
CHECKPOINT
  ↓
WAL COMPACTION / GC
```

核心 ordering：

$$
\boxed{
\text{snapshot durable}
\prec
\text{COMMIT durable}
\prec
\text{HEAD visible}
\prec
\text{WAL truncation}.
}
$$

---

# 3. Recovery Dichotomy

若 crash 發生在：

$$
\text{COMMIT durable}
$$

之前，

則：

$$
\boxed{
\operatorname{Recover}(T)
=
S_t.
}
$$

如果 child snapshot 已被寫入但沒有 COMMIT，它只是 orphan staging artifact，不能成為 HEAD。

若 COMMIT 已 durable，

則：

$$
\boxed{
\operatorname{Recover}(T)
=
S_{t+1}.
}
$$

如果 HEAD 尚未更新，recovery 必須 roll-forward。

---

# 4. HEAD Before COMMIT 是 Visibility Violation

即使 crash recovery 最後能 rollback，

如果 runtime 在 COMMIT 前就：

```text
HEAD := child
```

讀者已可能看到未提交 child。

因此：

$$
\boxed{
\text{recoverable}
\not\Rightarrow
\text{atomic}.
}
$$

Crash safety 必須同時包含：

- post-crash recoverability；
- pre-crash visibility safety。

---

# 5. WAL Truncation Ordering

如果：

1. COMMIT 已 durable；
2. HEAD 尚未 durable；
3. WAL 被先截斷；
4. crash；

那麼 transaction 可以「已承諾但消失」。

因此：

$$
\boxed{
\text{WAL truncate}
\succ
\text{HEAD durable}
}
$$

且實務上應在 checkpoint / lineage persistence 後再 compact。

---

# 6. Redo Sufficiency

COMMIT 存在但 child snapshot blob 遺失時，如果 WAL 還保存：

- parent identity；
- mutation event；
- deterministic runtime version；

則可以：

$$
\boxed{
\text{REDO from WAL}.
}
$$

Round 09 已實測此路徑。

但如果：

- COMMIT 存在；
- child blob 不在；
- mutation EVENT 也不在；

則：

$$
\boxed{
\operatorname{UNRECOVERABLE}.
}
$$

所以 COMMIT barrier 前必須確保：

$$
\boxed{
\text{durable child blob}
\lor
\text{durable deterministic redo material}.
}
$$

v0.9 的推薦仍是兩者都保留到 checkpoint 完成。

---

# 7. Idempotent Recovery

每個 transaction 必須有 stable：

$$
\mathrm{txid}.
$$

recovery 看到已 committed / already applied 的同一 txid 時：

$$
\boxed{
\operatorname{Replay}(T)^n
=
\operatorname{Replay}(T),
\quad
n\ge1.
}
$$

這是 local closure-state idempotency。

它不是 distributed-systems 意義下對所有外部 side effects 的 exactly-once guarantee。

若 mutation 同時觸發外部不可逆 action，需要另外的 outbox / idempotency-key protocol。

---

# 8. Immutable Snapshot Manifest

每個 committed epoch 保存：

```yaml
manifest:
  epoch: ...
  parent_epoch: ...
  parent_manifest_hash: ...
  tx_id: ...
  event_digest: ...
  state_hash: ...
  certificate_snapshot_hash: ...
manifest_hash: ...
```

因此：

$$
H_t
=
h(
E_t,
E_{t-1},
H_{t-1},
\mathrm{txid}_t,
h(\mu_t),
h(S_t),
h(\mathcal C_t)
).
$$

這形成 closure lineage hash chain。

---

# 9. Lineage Validation

重啟或 audit 時至少檢查：

1. epoch 連續；
2. parent epoch 正確；
3. parent manifest hash 正確；
4. txid 不重複；
5. state hash 正確；
6. certificate snapshot hash 正確；
7. manifest hash 正確。

任何一項失敗：

$$
\boxed{
\operatorname{LINEAGE\_INTEGRITY\_FAILURE}.
}
$$

不能靜默接受。

---

# 10. Staged Snapshot 不可直接可見

transaction 中途可有：

$$
S^{\mathrm{stage}}.
$$

但 reader 只能透過：

$$
\mathrm{HEAD}
$$

取得 committed epoch。

因此：

$$
\boxed{
\mathrm{Visible}(S)
\iff
S=\mathrm{Snapshot}(\mathrm{HEAD}).
}
$$

不可讓 staging namespace 被普通讀者當 closure snapshot。

---

# 11. Snapshot State Machine

建議：

```text
ABSENT
  ↓
STAGED
  ↓
COMMIT_DURABLE
  ↓
VISIBLE_HEAD
  ↓
CHECKPOINTED
  ↓
ARCHIVED / GC-ELIGIBLE
```

其中：

- `STAGED` 不可讀；
- `COMMIT_DURABLE` crash 後必 roll-forward；
- `VISIBLE_HEAD` 已對外；
- `CHECKPOINTED` 後才可安全 compact WAL。

---

# 12. Recovery State Machine

重啟後：

## No COMMIT

```text
ROLLBACK_UNCOMMITTED
```

## COMMIT + child blob valid

```text
ROLL_FORWARD_HEAD
```

## COMMIT + child blob missing + redo material sufficient

```text
REDO_FROM_WAL
→ validate target hash
→ ROLL_FORWARD_HEAD
```

## COMMIT + child blob missing + redo data insufficient

```text
UNRECOVERABLE
```

不得猜測。

---

# 13. Orphan GC

沒有 COMMIT 保護的 staged child：

$$
E>E_{\mathrm{HEAD}}
$$

可在 recovery 後 GC。

但 committed child 即使 HEAD 尚未 advance，也不可 GC。

因此 GC 判準必須讀 WAL / commit index，而不是只看 HEAD。

---

# 14. Checkpoint 與 WAL Compaction

checkpoint 至少保存：

- current epoch；
- current manifest hash；
- committed tx watermark；
- runtime schema / evaluator version；
- root registry digest；
- certificate registry digest。

只有 checkpoint durable 後，才能 compact 早期 WAL。

---

# 15. Runtime / Evaluator Version 必須進 Recovery Identity

如果 tx 的 redo 是由 runtime：

$$
R_v
$$

生成，

重啟後 runtime 已更新成：

$$
R_{v+1},
$$

直接 redo 可能產生不同 child hash。

所以 WAL / checkpoint 應保存：

```yaml
runtime_version: ...
evaluator_digest: ...
```

如果版本不相容：

$$
\boxed{
\operatorname{REDO\_VERSION\_MISMATCH}
}
$$

而不是偷偷用新版重算舊 COMMIT。

---

# 16. Round 08 Replay Artifact Gap

Round 08 notebook 內部確實從 genesis replay 過 transaction。

但 downloadable `round08_replay.py` 只驗：

- log count；
- stored snapshot hashes；
- final incremental/full files 相等。

它沒有攜帶完整 engine 重新執行 mutation。

Round 09 修正這個 reproducibility gap：

```text
round09_crash_runtime.py
```

本身就是可直接重跑的完整 crash / recovery simulator。

因此：

$$
\boxed{
\text{artifact replayability}
\neq
\text{internal notebook replayability}.
}
$$

---

# 17. Persistent QRSRC

v0.9 將 QRSRC 持久化為：

$$
\boxed{
\operatorname{PQRSRC}
=
(
G_C,
\mathcal C,
R,
W,
H,
L
)
}
$$

其中：

- $G_C$：closure graph；
- $\mathcal C$：certificate snapshot；
- $R$：root state；
- $W$：WAL；
- $H$：HEAD；
- $L$：snapshot lineage。

---

# 18. Crash-Consistency Criterion

對任意 transaction：

$$
T:S_t\rightarrow S_{t+1},
$$

任意 crash cut：

$$
k,
$$

要求：

$$
\boxed{
\operatorname{Recover}
(
\operatorname{Crash}_k(T)
)
\in
\{
S_t,S_{t+1}
\}.
}
$$

並且：

$$
\boxed{
\operatorname{Integrity}
(
\operatorname{Recover}(\cdot)
)
=
1.
}
$$

沒有 mixed epoch。

---

# 19. 新原理

## 原理一

$$
\boxed{
\text{Recoverability}
\neq
\text{Atomic Visibility}.
}
$$

## 原理二

$$
\boxed{
\text{COMMIT durability}
\Rightarrow
\text{eventual child visibility after recovery}.
}
$$

## 原理三

$$
\boxed{
\text{No COMMIT}
\Rightarrow
\text{child must never survive as committed HEAD}.
}
$$

## 原理四

$$
\boxed{
\text{WAL truncation is a lineage operation, not housekeeping}.
}
$$

## 原理五

$$
\boxed{
\text{Replayability requires executable recovery semantics, not only stored hash comparison}.
}
$$
