# 实战：发布规约 baseline v0.1

LLMS 索引： [llms.txt](/llms.txt)

---

本节把方法落到一个可发布对象：25 条 active rules、13 个交付资产、三类质量门、一份未来证据账本。发布的含义不是宣布“以后永不修改”，而是固定版本、范围、checksum、已知缺口和升级条件，让任何读者都能复核 v0.1 当时究竟承诺了什么。

实验风险：

- `static`：`R0·观察`，只读 repository，不连接 PostgreSQL；
- `live`：`R0·观察`，连接已确认 ch04-v1 L1，只读 session/catalog/data；
- `negative`：`R0·受控失败`，只改变本 session 参数或 expected target，要求精确失败；
- `review` / `all`：组合上述三类，不创建持久对象、不写业务数据。

即使是 R0，也必须指向已确认 target：catalog 与 query text 可能包含业务信息，过宽监控身份也可能越权。本章使用教学 L1 的 direct admin service。

## 6.7.1 审查 ch01–ch05 已出现的候选规则 {#item-6-7-1}

第一轮不从空白页“想 25 条最佳实践”，而是回看前五章的可重复证据：

| 来源 | 已验证事实 | 收敛出的规则族 |
|---|---|---|
| ch01 | target、role/schema ownership、危险 reset | CONN / ROLE / DEST |
| ch02 | service file、session context、脚本 evidence | CONN / SECR / SESS / EVID |
| ch03 | 业务不变量、关系/标识边界、fixture | NAME / KEYS / FIXT |
| ch04 | type、named constraint、migration、partition ADR | CONS / MIGR / TYPE / PART |
| ch05 | query path、failed transaction、lock/retry evidence | QUER / PAGE / TXNN / RETR / PLAN |

[`baseline-v0.1.json`](/labs/ch06/baseline-v0.1.json) 中每个 `evidence` item 都包含：

```json
{
  "chapter": "ch05",
  "artifact": "/labs/ch05/transaction-errors.sql",
  "observation": "首个错误后观察 25P02，并由显式恢复闭合。"
}
```

artifact 必须存在于当前 repository，chapter 必须属于 v0.1 source set，observation 必须说出从资产观察了什么。checker 还要求五章都至少贡献 active evidence，防止版本说明宣称覆盖 ch01–ch05，实际只引用其中两章。

### 从候选到 25 条 active rule

审查按四步进行：

1. 合并同一失败机制的重复句子；
2. 把同时包含多个独立风险的句子拆开；
3. 评估后果，定为 safety/default/preference；
4. 为每条规则指定最小 check 与 exception mode。

最终分组如下：

| Safety（10） | Defaults（10） | Preferences（5） |
|---|---|---|
| target、secret、role、definer | session、context、name、type | text |
| constraint、migration、txn failure | key、query、txn size | semi-structured |
| retry、destructive action、pagination | fixture、evidence、version | partition、advanced SQL、plan |

完整标题在 [`baseline-guide.md`](/labs/ch06/baseline-guide.md) 中。指南只出现一次每个 Rule ID；详细 statement/rationale/evidence/exception/checks 以 JSON registry 为准。若人类指南与 registry 分叉，static gate 失败。

### 对等级做一次对抗性复核

每条 safety 都反问：

- 违反是否真的可能直接导致数据错误、越权、不可恢复动作或不可归因事故；
- 是否存在同样安全但不满足当前 statement 的合理方案；
- `none` 与 `breakglass` 是否被正确选择；
- 当前 check 是否能看见失败机制，而不是只检查格式。

每条 default 都反问：

- 统一默认真正减少了什么测试/维护矩阵；
- 哪些 workload 合理偏离；
- waiver 是否有可验证补偿和 expiry。

每条 preference 都反问：

- 它是否只是作者品味；
- 是否存在多个同样正确的方案；
- review 需要什么 workload/计划/维护证据。

这一步把“稳定分页”从普通 SQL 风格提升为 safety，因为无全序会直接破坏 API 跨页正确性；同时把 `text`、分区与高级 SQL 保留为 preference，避免把场景判断伪装成数据库铁律。

### 已知缺口必须进入输出

`SAFE-RETR-008` 的失败后果足以成为 safety，但 ch01–ch05 尚未提供完整多会话 retry harness。它的 check 仍只有：

```text
review:
  SQLSTATE allowlist、最大次数、deadline、idempotency key、
  ambiguous outcome 查询
```

因此 checker 计算“至少一个 automated/runtime check 的 safety”时输出 9，不允许作者手工写成 10。ch10 必须补入 `40001`/`40P01` 整体重试、bounded backoff 与 outcome reconciliation 的运行证据。这就是版本化 baseline 与普通文档清单的差别：未知被编码进验收，而不是藏在脚注里。

## 6.7.2 为 `pg36_shop` 建立最小质量门 {#item-6-7-2}

先下载/进入资产目录：

```bash
cd static/labs/ch06
```

### 第一道门：static

不设置任何数据库环境变量也能运行：

```bash
export PG36_EVIDENCE_DIR="$PWD/evidence/ch06/static-$(date -u +%Y%m%dT%H%M%SZ)"
./quality-gate.sh static
```

`baseline-check.txt` 的稳定摘要应为：

```text
status=ok
baseline_version=0.1.0
rule_count=25
safety_count=10
default_count=10
preference_count=5
safety_non_review_count=9
source_chapter_count=5
artifact_reference_count=23
delivery_artifact_count=13
scanned_source_count=45
baseline_checksum=bb1404e2b2e47624b17f3a1b0de63a5371f382b67906f1a8ba1cf08e92895a1c
```

`baseline_checksum` 是按规范化 JSON 计算的 registry 内容指纹，不等于文件原始 bytes 的 `sha256sum`。改变缩进不会改变 canonical checksum，改变规则、兼容范围或证据会改变。`manifest.txt` 另行保存 13 个文件的原始 SHA-256，以便复现本次具体输入。

数量会在新版本有意变化；v0.1 内若静默变化，必须先解释 registry/manifest diff 并更新本文验收，不能为了让 CI 绿而改 expected count。

static action 还输出：

- `shell-syntax.txt`：本书受管 lab shell 的 `bash -n` 结果与数量；
- `baseline-check.stderr`：成功时为空；
- evidence-local Python bytecode：不污染 source tree；
- `gate-summary.txt`：`static=pass`，live/negative 为 skipped。

### 第二道门：live

先确认 ch04-v1：

```bash
export PGSERVICEFILE=/absolute/private/path/pg_service.conf
export PGSERVICE=pg36-admin

psql -X -w "service=$PGSERVICE" \
  -c '\conninfo' \
  -c "SELECT current_database(), pg_is_in_recovery();"
```

service 必须指向 `pg36_shop` 的 direct writable primary，登录身份可受控 `SET ROLE pg36_owner`。然后：

```bash
export PG36_EVIDENCE_DIR="$PWD/evidence/ch06/live-$(date -u +%Y%m%dT%H%M%SZ)"
./quality-gate.sh live
```

执行路径：

```text
session-profile
  → ch05 verify（复用 ch04 完整模型后验）
  → query-contract
  → server facts
```

`session-profile.txt` 应证明 UTF8、UTC、`pg_catalog, shop`、三类 timeout 和 application name；`model-verify.txt` 应保留：

```text
status=ok
model_version=ch04-v1
lab_state=rollback-only
active_lab_workers=0
relation_checksum=f8a7bfae59c6d16cd323abecfefe1014
```

`query-contract.txt` 应证明 11 列 view shape、稳定 keyset 顺序、两页不重叠、business/idempotency key 唯一。live 全部是 read-only；如果 relation checksum 改变，说明前置状态已经漂移，不能用本章脚本修复。

### 第三道门：negative

在同一已确认 L1：

```bash
export PG36_EVIDENCE_DIR="$PWD/evidence/ch06/negative-$(date -u +%Y%m%dT%H%M%SZ)"
./quality-gate.sh negative
```

稳定摘要：

```text
status=ok
wrong_session_exit=3
wrong_session_sqlstate=P0601
wrong_target_exit=3
wrong_target_sqlstate=P0001
```

这里 `status=ok` 表示**两个错误都按预期被拒绝**，不是错误 SQL 成功。stdout/stderr 分开保存，可以复核 SQLSTATE 恰好出现一次。

### 发布候选：review/all

`review` 与 `all` 当前执行同一条完整路径；前者强调人工发布语义，后者适合作为自动任务 action：

```bash
export PG36_EVIDENCE_DIR="$PWD/evidence/ch06/review-$(date -u +%Y%m%dT%H%M%SZ)"
./quality-gate.sh review

cat "$PG36_EVIDENCE_DIR/gate-summary.txt"
```

预期：

```text
status=ok
gate_version=ch06-v0.1
action=review
static=pass
live=pass
negative=pass
baseline_checksum=bb1404e2b2e47624b17f3a1b0de63a5371f382b67906f1a8ba1cf08e92895a1c
relation_checksum=f8a7bfae59c6d16cd323abecfefe1014
```

只有同时检查 source diff、baseline canonical checksum、model checksum、wrong-session/target 和 evidence manifest，才批准 v0.1。动态 server version、timestamp、PID 不做 golden。

### Gate 的失败边界

完整 action 未设置 `PGSERVICEFILE` 时必须在连接前以 usage/exit 64 拒绝；未知 action 同样退出 64。缺少工具退出 69。数据库或断言失败保留非零 `psql`/script exit，不改写成绿色 summary。

gate 不负责：

- 自动安装 PostgreSQL/Pigsty；
- 自动创建/修复 ch04 模型；
- 自动注入 credential；
- 自动 apply Pigsty inventory；
- 自动批准 waiver/breakglass；
- 自动对生产执行 migration/reset。

这些边界让错误前置条件尽早暴露，也防止“质量脚本”获得超出检查所需的修改权限。

## 6.7.3 预留 ch07–ch11 的证据追加区 {#item-6-7-3}

[`evidence-ledger.md`](/labs/ch06/evidence-ledger.md) 已固定下一阶段的证据路线：

| 版本候选 | 章节 | 必须新增的运行证据 | 主要影响 |
|---|---|---|---|
| v0.2 | ch07 | estimate/actual、statistics、plan settings | `PREF-PLAN-005` |
| v0.3 | ch08 | workload attribution、wait taxonomy、慢查询闭环 | `DEFAULT-EVID-009` |
| v0.4 | ch09 | index benefit/cost、write amplification、concurrent build | `PREF-PLAN-005` |
| v0.5 | ch10 | lost update、write skew、deadlock、40001 retry | `SAFE-RETR-008` |
| v0.6 | ch11 | expand/contract、lock budget、application compatibility | `SAFE-MIGR-006` / `DEFAULT-VERS-010` |

版本号是候选节奏，不要求每章机械升级。若新证据只重复原结论，可以追加 ledger 而不改 statement；若发现 scope、level、exception 或 check 需要变化，则发布新 minor version，并说明：

```text
added / changed / deprecated Rule ID
old → new semantics
compatibility impact
waiver migration
gate/evidence changes
```

不要改写 v0.1 文件后仍称 v0.1。最简单的历史保护是保留不可变 release artifact/tag 与 checksum；主干上的“current”可以指向最新版本。

### 新证据既可能收紧，也可能撤销规则

例如 ch07 可能证明某种统计问题才是估算失真的根因，因而 `PREF-PLAN-005` 应增加 statistics check，而不是升级成“禁止 Seq Scan”。ch10 可能发现某类 transaction 因外部副作用无法自动 retry，于是 safety statement 需要收紧 idempotency/reconciliation，而不是只加重试次数。

规则体系的价值不在于永远维护最初判断，而在于让反例可以有秩序地改变判断。

### 每章回写的最小格式

追加证据至少记录：

```text
chapter + artifact + exact observation
PostgreSQL/Pigsty/OS compatibility
positive + negative result
rule impact（confirm / narrow / expand / deprecate）
check automation change
new exception/waiver impact
```

生产 incident 可以成为证据，但必须去除敏感数据并保留足够机制信息；不能只写 incident ticket URL，让离线读者无法理解结论。

## 6.7.4 在 ch12 汇总为 v1.0 的验收条件 {#item-6-7-4}

ch12 不是把 v0.6 改名为 v1.0。它要在一个真实后端服务交付中贯通：

```mermaid
flowchart LR
  A["Pigsty desired state"] --> B["角色 / DB / services"]
  B --> C["versioned schema"]
  C --> D["application query + transaction"]
  D --> E["pool / routing / observability"]
  E --> F["failure + retry + release"]
  F --> G["v1.0 evidence bundle"]
```

v1.0 必须同时满足：

1. 每条 active rule 至少有一个可重复实验或已脱敏生产事件证据；
2. 所有 safety 都有 automated 或 runtime gate，不只依赖文字 review；
3. 每个 active exception 有 owner、expiry、补偿控制与复核结果；
4. query/transaction/DDL 规则在同一个后端服务交付中实际走完；
5. static、live、negative 可在统一 L1 重跑；
6. v0.x 的 false positive、false negative、waiver 与 incident 已回写 rationale；
7. compatibility matrix 对 PostgreSQL 14–18 与当前 Pigsty baseline 有明确结果或限制；
8. pooled application path、direct migration path 与 failover route 均有证据；
9. v1.0 有从 v0.x 迁移说明，不静默改变既有 Rule ID 语义；
10. release artifact、source manifest、canonical checksum 与签署 owner 完整。

若 ch10 未把 safety 覆盖从 9/10 提升到 10/10，或者 ch12 只在 direct admin session 验证而没有 application/pool path，v1.0 必须推迟。deadline 不能改变验收事实。

### v0.1 发布记录

当前发布候选：

```text
baseline_version=0.1.0
published_on=2026-07-29
postgresql=14-18
validated_postgresql=18.6
pigsty=4.5.0
target_os=Ubuntu 24.04 L1
local_validation=PostgreSQL 18.6/Homebrew on macOS
rules=25
safety_enforced_by_auto_or_runtime=9/10
canonical_checksum=bb1404e2b2e47624b17f3a1b0de63a5371f382b67906f1a8ba1cf08e92895a1c
```

这个记录只在完整 `review` gate 与全书 structure/link/build 检查通过后成立。任何 registry 语义变更都应产生新 checksum 和新版本；任何运行环境变化都应产生新的 evidence bundle，而不是覆盖旧证据。

到这里，我们没有得到一本万能的 PostgreSQL 风格指南，而是得到了一套可以被验证、质疑、例外、升级和审计的规则系统。下一章开始，性能与并发专题会不断用新证据挑战它。

---

[上一节：将规约接入统一实验环境](../06/) · [返回本章目录](../) · [下一章：追本溯源：执行计划与统计信息](/query-plans-statistics/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
