# 多 Agent 工程实施手册

版本：v0.3.0（启动前必改三件套 A7/A2/B1：高危域清单补齐 10 项并新增匹配规则与启动自检 / 状态机拆 current_phase 与 state 两维度并补齐出入边 / SQLite 并发配置与写事务重试；并修 6.8.2 断言数与附录 E 步骤数不一致）  
配套流程文档：《多 Agent 协作流程设计文档》v2.4.4  
状态：工程实施第一版  
适用范围：Code 层、工具层、CI/CD、运行环境、插件拦截层  
不适用范围：业务流程规则本身（流程规则以配套流程文档为准）

---

## 0. 手册定位

### 0.1 与流程文档的边界

流程文档定义：

- 什么阶段必须做什么
- 哪些动作必须人工审批
- 哪些边界不可突破
- 失败、验收、预算、重写的业务规则

本手册定义：

- Code 层如何实现这些规则
- 状态如何持久化
- 并发如何隔离
- 插件如何硬拦截
- 测试如何验收
- 事故如何回滚
- 成本如何记账

冲突处理原则：

1. 流程文档的业务硬边界优先。
2. 本手册不得放宽流程文档中的硬规则。
3. 本手册可以增加更严格的工程保护。
4. 如果工程实现与流程语义冲突，必须暂停实现并提交人工裁定，不得静默改流程。

### 0.2 工程总原则

1. **所有硬边界必须可测试**：不能只写在文档里，必须有回归用例。
2. **所有状态必须可恢复**：进程重启后不得导致重复派发、重复写入、重复部署。
3. **所有副作用必须可追踪**：写文件、执行命令、部署、迁移数据都必须有日志、哈希、回滚点。
4. **所有人工审批必须有时限**：不允许任务永久悬挂。（起步期例外：本机没有计时器——改由 `mtask` 待办 + 每日 09:00 提醒兜底，见《流程文档》第九节勘误。）
5. **所有规则尽量单一事实源**：可机器执行规则优先收敛到 `rules.json` 或等价配置。

---

## 0.3 资源预算与单机运行限制

在低资源单机环境中，必须先声明资源预算，再决定并行度和任务类型。

典型低资源环境特征：

1. CPU 核心数 ≤ 2。
2. 可用内存 ≤ 1GB（本机实测 2026-09-19：总内存 1.6GB，常态可用 660–770MB；
   当日停用并 mask 掉云主机上无用的 fwupd / packagekit / multipathd 后多出约 175MB，原先常态约 490MB）。
3. 无 swap（2026-09-19 复测确认；加 swap 属系统级改动，须人工批准，未加之前一律按“无 swap”保守处理）。
4. 无 Docker 或其他容器运行时（2026-09-19 复测：docker / podman 均不存在）。
5. 本地磁盘有限（根分区 40GB，实测剩余约 26GB）。

在该类环境中必须启用单机保守模式：

| 限制项 | 要求 |
|---|---|
| `max_workers` | **起步期 = 1（唯一权威值）**；硬上限 2；放开到 2 的条件 = 文件所有权机制连续 3 次派发零冲突且声明无交集 |
| 并行条件 | 仅允许轻量任务并行 |
| 编译 | 不得本地并行，优先提交 CI |
| 完整测试 | 不得本地并行，优先提交 CI |
| 打包 / 构建 | 不得本地并行 |
| 依赖安装 | 必须串行，并加锁 |
| 容器构建 | 无容器环境禁止 |
| 数据迁移 | 必须串行，并提前备份 |
| 浏览器 / UI 测试 | 禁止 headed 实例与多实例并行；允许**单实例 headless** 轻量抓取与截图（本机实测：headless 稳定可用，headed 会导致 daemon 无响应） |

> **权威源声明（2026-09-19 复核修正）**：`max_workers` 的唯一权威值以本节为准 = **起步期 1**；流程文档 v2.4.4 已同版勘误统一为 1（此前写 2 的一版勘误作废）。
> 注意：本机 worker 是远端 API 调用（Hermes 子代理），**不吃本地内存** —— 这个数字的约束来自工作区冲突（2026-09-19 实战：无锁、2~3 并发 → 3 次文件冲突告警），不是 RAM。

轻量任务定义：

1. 文本生成。
2. 代码阅读。
3. 小规模 diff。
4. Reviewer 验收。
5. 文档整理。
6. 日志摘要。
7. 不涉及重型编译或大量 I/O 的任务。

重活定义：

1. 编译。
2. 完整测试套件。
3. 打包。
4. 依赖安装。
5. 容器构建。
6. 数据库迁移。
7. 大文件处理。
8. 高内存工具调用。
9. 多进程并行测试。

派发前必须进行资源预检：

1. 可用内存。
2. 可用磁盘。
3. 当前负载。
4. 端口占用。
5. 是否已有重型任务运行。
6. 是否超过 `max_workers`。

资源不足时：

1. 不得启动新 worker。
2. 任务状态置为 `blocked` 或 `paused`。
3. 记录阻塞原因。
4. 已运行任务应先保存现场，再暂停或终止。
5. 不得因资源不足直接静默失败。

验收标准：

1. 在约 600MB 可用内存下，并行轻量任务不应触发 OOM。
2. 编译、完整测试、打包等重活不会在本地并行执行。
3. 超过 `max_workers` 时，新任务被阻塞而不是启动。
4. 资源不足时有明确日志和状态。
5. 重活被路由到 CI 或串行队列。

---

# 第一章 状态机与持久化

## 1.0 宿主与编排器层

本手册默认存在一个长期运行的宿主编排器。编排器不是聊天会话，也不是短生命周期子代理，而是常驻进程或等价守护进程。

宿主形态选择：

| 优先级 | 形态 | 说明 |
|---|---|---|
| 首选 | systemd user service | 本机现状：systemd 249（Ubuntu 22.04），已在运行 4 个 Hermes 相关 unit（gateway / apk-server / tailnet-proxy / public-proxy），编排器直接作为第 5 个 unit 加入即可 |
| 备选 | supervisor / pm2 / runit | 非 systemd 环境使用 |
| 最低级 | cron + wrapper | 仅适合批处理任务，不支持长驻状态 |

⚠️ 已知环境约束（实测修正）：`OOMPolicy=` 是 **service unit 属性**——写在 **scope unit** 上会报 `Unknown assignment: OOMPolicy=kill`（本机 systemd 249 实测：`systemd-run --user --scope --property OOMPolicy=kill` 失败，`systemd-run --user --property OOMPolicy=kill` 成功）。曾因此导致定时任务 worker 整体不可用。

反向收益：编排器做成 **service unit** 时该属性可用，在总内存 1.6GB / 无 swap 的环境下建议启用 OOM 自保：

```ini
[Service]
OOMPolicy=stop
OOMScoreAdjust=-500
```

编排器必须持有并管理以下内容：

1. SQLite 或其他持久化状态库。
2. 任务状态机。
3. 文件锁、资源锁、环境锁。
4. 预算计数与熔断状态。
5. worktree / 临时工作区生命周期。
6. 工具调用日志与产物 manifest。
7. `rules.json` 或等价规则版本。
8. Checkpoint 审批状态与超时计时。

LLM 会话、子代理、delegate、临时 shell 进程都属于短生命周期执行器。它们退出、被 `/new`、被 `/stop`、崩溃或重启时，不得导致任务状态丢失。

强制要求：

1. 所有关键状态必须在每次状态迁移后落盘。
2. 子代理不得作为长期状态存储。
3. 聊天上下文不得作为任务恢复依据。
4. 每个任务必须使用独立 worktree 或独立临时工作区。
5. 编排器重启后必须从 DB 恢复到最近稳定检查点。
6. 子代理丢失时，任务状态应置为 `paused`、`needs_recovery` 或 `blocked`，不得静默消失。

禁止事项：

1. 禁止依赖“子代理还记得任务”继续执行。
2. 禁止把 `/new` 后的会话当作原任务延续。
3. 禁止用人工记忆或聊天历史替代 SQLite 状态。
4. 禁止多个任务共享同一 worktree。
5. 禁止编排器退出后未保存锁、预算和任务状态。

验收标准：

1. 杀死编排器进程后重启，可恢复任务状态。
2. 杀死子代理后，任务不会丢失，只进入可恢复状态。
3. `/new` 或 `/stop` 后，任务状态仍可从 DB 查询。
4. 两个并行任务不会写入同一 worktree。
5. 编排器重启不会重复派发已派发的非幂等操作。

---


## 1.1 端到端任务状态机

### 1.1.1 状态实体

至少需要五类实体：

| 实体 | 说明 |
|---|---|
| Task | 一次完整多 Agent 任务 |
| Module | Phase 2 切出的模块 |
| WorkerRun | 一次 worker 执行 |
| Review | 一次 reviewer 验收 |
| Checkpoint | 人工审批节点 |

### 1.1.2 Task 生命周期：flow position 与 run state 两维度

**决策（A2 方案 A）**：流程位置与运行状态是两个正交维度，不得塞进同一枚举——
1.1.5 第 5 条禁止同一实体存在两个互斥状态，而 `running → paused_for_budget → running`
这类迁移在单字段下恢复后无法定位回到哪个阶段。故拆为两个字段：

```text
tasks.current_phase : NULL | phase_minus_1 | phase_0 | phase_1 | phase_2 | phase_3 | phase_4 | phase_5 | phase_6
                      —— 流程位置：单向推进，允许在 Checkpoint 拒绝时回退
tasks.state         : 运行状态（下表）
```

```text
created
running                 ← A2 新增
paused                  ← A2 新增（4.7.1 pause 的落点）
needs_recovery          ← A2 新增（1.2.3 第 3 条半完成副作用的落点）
blocked
checkpoint_pending
paused_for_budget
circuit_broken
escape_compromise
escape_advisor
escape_bypass
controlled_rewrite
failed
passed
delivered
cancelled
aborted
archived
```

状态与阶段必须同时落库：`tasks.state` 与 `tasks.current_phase` 任一缺失即视为非法行。

### 1.1.3 状态迁移要求

每次状态迁移必须记录：

```json
{
  "entity_type": "task | module | worker_run | review",
  "entity_id": "string",
  "from_state": "string",
  "to_state": "string",
  "phase_from": "phase_* | null",
  "phase_to": "phase_* | null",
  "reason_code": "string",
  "actor": "code | orchestrator | human | plugin",
  "timestamp": "ISO8601",
  "evidence_uri": "string | null"
}
```

### 1.1.4 关键迁移规则

表中「to」一律指 `state`；涉及阶段变化时同时给出 `current_phase` 的目标值。

| 当前 state | 可迁移到 | 条件 | current_phase 变化 |
|---|---|---|---|
| created | running | 任务登记完成 | → phase_minus_1 |
| running | cancelled | 任一三问不通过（回 Phase -1 判定） | 保持 |
| running | paused | 人工 pause（见 4.7.1） | 保持 |
| paused | running | 人工 resume | 保持 |
| paused | cancelled / aborted | 人工取消 / 强制终止 | 保持 |
| running | needs_recovery | 重启后发现半完成副作用（1.2.3 第 3 条） | 保持 |
| needs_recovery | paused | 人工确认现场后挂起 | 保持 |
| needs_recovery | blocked | 需外部介入 | 保持 |
| needs_recovery | failed | 人工判定放弃 | 保持 |
| running | checkpoint_pending | 到达 Checkpoint 节点 | → 对应 phase |
| checkpoint_pending | running | 人工批准 | → 下一 phase |
| checkpoint_pending | running | 人工拒绝，回退补 brief | → 上一 phase |
| checkpoint_pending | paused | SLA 超时，落 hold_safe_state（对应 A3 落点） | 保持 |
| running | paused_for_budget | 单任务超预算 120% | 保持 |
| running | circuit_broken | 全局预算池耗尽 | 保持 |
| paused_for_budget | running | 人工批准或预算追加 | 恢复为暂停前 phase |
| running | escape_compromise | L2 首次漂移且非高危域（见 3.1.3） | 保持 |
| running | escape_advisor | L2 顾问模式，或高危域漂移（3.1.3） | 保持 |
| escape_compromise | escape_advisor | 持续失败升级 | 保持 |
| escape_compromise | running | 修复后回执行（【需确认】是否允许自动回） | 保持 |
| escape_advisor | escape_bypass | L3 批准旁路 | 保持 |
| escape_advisor | controlled_rewrite | L3 批准受控重写 | 保持 |
| escape_advisor | failed | L3 判定放弃 | 保持 |
| escape_bypass | passed | 带已知偏差通过，必须写技术债（3.2） | 保持 |
| controlled_rewrite | running | 重写完成，重新进入验证 | 保持 |
| running | passed | Phase 6 通过 | → phase_6 |
| passed | delivered | 产物完整 | 保持 |
| delivered | archived | 交付归档 | 保持 |
| circuit_broken | archived | 人工确认收尾 | 保持 |
| blocked | running | 阻塞解除 | 恢复为阻塞前 phase |

**硬约束**：`needs_recovery` 不得直接回到 `running`（1.4.4 第 1、3 条），必须经人工确认。
原先 `escape_bypass` 零入边零出边、`escape_compromise` / `escape_advisor` 只有入边——
进去出不来会致任务永久悬挂，违反 0.2 原则 4，本表已补齐。

### 1.1.5 禁止事项

1. 禁止从失败状态直接跳到交付状态。
2. 禁止绕过 `checkpoint_pending` 直接进入下一阶段。
3. 禁止人工或 LLM 直接修改状态机枚举。
4. 禁止状态迁移无日志。
5. 禁止同一实体同时存在两个互斥状态。
6. 禁止 `needs_recovery` 直接迁移到 `running`（必须经人工确认，见 1.4.4）。
7. 禁止只更新 `state` 而不更新 `current_phase`（或反之）；两者必须同事务写入。

---

## 1.2 SQLite / DB 持久化与幂等

### 1.2.1 持久化最小表

至少包含：

| 表 | 作用 |
|---|---|
| tasks | 任务主状态 |
| modules | 模块状态 |
| worker_runs | worker 执行记录 |
| reviews | reviewer 结果 |
| checkpoints | 人工审批 |
| budget_events | 预算事件 |
| tool_calls | 工具调用记录 |
| artifacts | 产物清单 |
| locks | 文件/资源锁 |
| debt_records | 技术债 |
| cost_ledger | 成本账本 |
| rule_versions | 规则版本 |

#### 1.2.1.1 SQLite 并发配置（B1，强制）

默认配置下 `journal_mode=DELETE` 且 `busy_timeout=0`：**多 worker 并发写会立即返回 `SQLITE_BUSY` 并丢状态**，必须显式配置。

| PRAGMA | 值 | 级别 | 说明 |
|---|---|---|---|
| `journal_mode` | `WAL` | 库级（持久化） | 读写不互阻；设一次即可。注意 WAL 仍只允许单写者 |
| `busy_timeout` | `5000` | **连接级** | 写锁等待上限；每个新连接都要设 |
| `synchronous` | `NORMAL` | 连接级 | WAL 下安全，断电只丢最近事务 |
| `foreign_keys` | `ON` | 连接级 | 默认 OFF，易漏约束 |
| `wal_autocheckpoint` | `512` | 连接级 | 低内存档调小，及时回写 |
| `journal_size_limit` | `8388608` | 库级 | 限制 WAL 增长，防 600MB 环境被撑爆 |
| `mmap_size` | `0` | 连接级 | 低内存档禁用 mmap |
| `temp_store` | `DEFAULT` | 连接级 | 600MB 下不用 MEMORY |

```python
def connect(db_path: str) -> sqlite3.Connection:
    conn = sqlite3.connect(db_path, timeout=5.0, isolation_level=None, check_same_thread=False)
    conn.execute("PRAGMA journal_mode = WAL")
    conn.execute("PRAGMA busy_timeout = 5000")
    conn.execute("PRAGMA synchronous = NORMAL")
    conn.execute("PRAGMA foreign_keys = ON")
    conn.execute("PRAGMA wal_autocheckpoint = 512")
    conn.execute("PRAGMA journal_size_limit = 8388608")
    conn.execute("PRAGMA mmap_size = 0")
    return conn
```

**写事务必须 `BEGIN IMMEDIATE` + 有限重试**：`busy_timeout` 只处理「等锁」，
处理不了 read-then-write 事务升级时的 `SQLITE_BUSY_SNAPSHOT`（该错误不重试），
故写路径统一走：`BEGIN IMMEDIATE` 取锁 → 失败按指数退避重试（上限 5 次）→ 仍失败才报错。

```python
MAX_RETRIES = 5

def write_txn(conn, fn, retries=MAX_RETRIES):
    for attempt in range(retries):
        try:
            conn.execute("BEGIN IMMEDIATE")
            result = fn(conn)
            conn.execute("COMMIT")
            return result
        except sqlite3.OperationalError as e:
            conn.execute("ROLLBACK")
            msg = str(e).lower()
            if "locked" in msg or "busy" in msg:
                time.sleep(min(0.05 * (2 ** attempt), 1.0) * (0.5 + random.random()))
                continue
            raise
```

短事务原则（busy_timeout 生效前提）：事务内禁止 LLM 调用、网络 IO、大文件读写、长查询；
先把数据算好再开事务。

低资源档注意：WAL 的 `-shm` 依赖共享内存，**DB 落在 NFS/网络盘时 WAL 不可用**，
须退回 DELETE 模式并更保守（部署路径需在启动前确认）。

### 1.2.2 幂等键

所有副作用操作必须带幂等键：

```text
idempotency_key = task_id:phase:module_id:attempt:operation_type:operation_hash
```

示例：

```text
task_123:phase4:M3b:attempt2:write_file:a1b2c3
```

### 1.2.3 重启恢复规则

进程重启后：

1. 读取最近一个稳定检查点。
2. 不得自动重放未确认副作用。
3. 对已执行一半的副作用必须进入 `needs_recovery`。
4. 可安全重跑的操作需显式标记 `idempotent=true`。
5. 不可幂等操作必须有补偿方案或人工审批。

### 1.2.4 租约机制

每个运行中 worker 必须有租约：

```json
{
  "worker_id": "string",
  "task_id": "string",
  "lease_expires_at": "ISO8601",
  "heartbeat_interval_seconds": 15
}
```

规则：

1. 租约过期视为异常退出。
2. 过期后不得立即释放写锁，必须先检查工作区。
3. 强制释放必须记录审计日志。

---

## 1.3 文件锁与资源锁

### 1.3.1 锁对象

锁不能只覆盖文件，必须覆盖五类对象：

| 锁类型 | 示例 |
|---|---|
| file | `src/auth/token-service/*` |
| resource | 数据库、端口、容器、缓存 |
| contract | 同一契约条目 |
| data | 共享数据集、迁移目标表 |
| environment | 共享测试环境 |

### 1.3.2 锁模式

| 模式 | 含义 |
|---|---|
| read | 多个任务可同时读 |
| write | 独占写 |
| intent_write | 准备写入，阻止新读锁 |
| advisory | 建议锁，用于提示领导 |
| hard | Code 层物理互斥 |

### 1.3.3 锁生命周期

锁的生命周期必须显式定义：

```text
申请 → 获取 → 续租 → 释放 / 超时回收 / 崩溃回收
```

### 1.3.4 崩溃回收

1. worker 崩溃后，锁不得永久保留。
2. 回收前必须保存现场。
3. 回收后必须通知领导进程。
4. 如果锁涉及写操作，必须检查工作区是否半完成。

### 1.3.5 死锁检测

1. 必须维护锁等待图。
2. 超过 60 秒未获取锁应告警。
3. 超过 300 秒应触发人工或自动降级串行。
4. 自动解锁必须记录原因。

---

## 1.4 进程被 kill 前的成果保全

### 1.4.1 触发场景

包括：

1. 工具调用超限。
2. 预算熔断。
3. 手动取消。
4. 系统资源不足。
5. 安全插件阻断。

### 1.4.2 保全动作

被终止前必须尽量完成：

1. 保存当前 workspace patch 或 git diff。
2. 保存工具调用日志。
3. 保存最后一条模型输出。
4. 释放或标记锁。
5. 写入 `termination_manifest`。

### 1.4.3 termination_manifest

```json
{
  "task_id": "string",
  "worker_id": "string",
  "reason": "tool_limit | budget | cancel | security_block | crash",
  "uncommitted_changes_path": "string | null",
  "lock_state": "released | needs_review",
  "partial_artifacts": ["string"],
  "resume_allowed": false,
  "timestamp": "ISO8601"
}
```

### 1.4.4 恢复规则

1. 默认不允许自动续跑。
2. 若允许续跑，必须通过幂等检查。
3. 有未完成写操作时必须人工确认。

---

## 1.5 流程版本迁移

### 1.5.1 版本绑定

每个任务启动时必须绑定：

```json
{
  "process_doc_version": "v2.4.4",
  "engineering_manual_version": "v0.3.0",
  "rules_version": "rules@2026-xx-xx",
  "prompt_version": "string",
  "contract_version": "string",
  "db_schema_version": "string"
}
```

### 1.5.2 升级策略

| 场景 | 策略 |
|---|---|
| 新任务 | 使用新版本 |
| 运行中任务 | 默认锁定旧版本 |
| 安全漏洞修复 | 可强制升级，但需人工批准 |
| DB schema 变更 | 必须写迁移脚本 |
| prompt 变更 | 必须过回归测试集 |
| rules.json 变更 | 必须过插件回归用例 |

### 1.5.3 旧任务兼容

1. 旧任务必须能按旧版本状态机恢复。
2. 如果旧版本无法恢复，必须转人工。
3. 不得静默用新规则恢复旧任务。

---

# 第二章 验证与测试工程

## 2.1 测试环境隔离

### 2.1.1 隔离原则

并行任务不得共享可变环境。

必须隔离：

1. 文件系统工作区。
2. 数据库实例或 schema。
3. 端口。
4. 缓存。
5. 对象存储路径。
6. 测试容器。
7. 环境变量。
8. 临时密钥。

### 2.1.2 最小隔离方案

| 等级 | 方案 |
|---|---|
| 最低 | 独立临时目录 + 独立 SQLite 文件 |
| 中等 | 独立 Docker 容器 + 独立数据库 schema |
| 推荐 | 独立容器 + 独立端口 + 独立卷 + 独立网络命名空间 |

### 2.1.3 清理

任务结束后必须清理：

1. 临时目录。
2. 测试数据库。
3. 端口占用。
4. 后台进程。
5. 未释放锁。
6. 临时凭据。

---

### 2.1.4 无容器隔离降级路径

当运行环境没有 Docker、Podman 或其他容器运行时，隔离不能直接失败，必须降级为轻量隔离档。

隔离档位分为两档：

| 档位 | 适用环境 | 隔离方式 |
|---|---|---|
| 容器档 | 有 Docker / Podman / 等价容器运行时 | 独立容器、独立卷、独立端口、独立网络命名空间 |
| 轻量档 | 无容器运行时，或低内存单机 | 独立 worktree、独立临时目录、独立端口、独立 SQLite 文件 |

轻量档最低要求：

1. 每个任务独立 `git worktree`；**任务目录不是 git 仓库时，退回独立临时目录档**。
2. 每个任务独立 SQLite 文件或独立数据库文件名。
3. 每个任务独立端口或端口范围。
4. 每个任务独立环境变量文件。
5. 每个任务独立缓存目录。
6. 每个任务独立日志目录。
7. 每个任务独立锁文件或锁命名空间。
8. 每个任务独立产物目录。

轻量档禁止共享：

1. 同一个 SQLite 文件。
2. 同一个构建目录。
3. 同一个依赖缓存目录。
4. 同一个端口。
5. 同一个浏览器实例。
6. 同一个本地服务进程。
7. 同一个临时 HOME。
8. 同一个 worktree。

轻量档限制：

1. 不适合并行运行重型编译。
2. 不适合并行运行完整测试套件。
3. 不适合并行运行数据库迁移。
4. 不适合并行启动多个长驻服务。
5. 重活必须走 CI、远程执行器或串行队列。

轻量档清理要求：

1. 任务结束后删除临时目录。
2. 释放端口。
3. 关闭子进程。
4. 删除或归档临时 SQLite 文件。
5. 清理锁文件。
6. 保留必要日志与产物 manifest。

验收标准：

1. 两个并行任务的文件路径无交集。
2. 两个并行任务不会争抢同一端口。
3. 一个任务崩溃后，另一个任务不受污染。
4. 清理脚本可删除任务残留。
5. 无容器环境下仍能完成轻量任务的隔离执行。

---

## 2.2 Flaky 测试处理

### 2.2.1 判定

| 现象 | 判定 |
|---|---|
| 首次失败，自动重跑通过 | 疑似 flaky |
| 同一测试 3 次中随机失败 | 标记 flaky |
| 连续失败且指纹稳定 | 不计 flaky，进入失败流程 |
| 环境类错误 | 走环境重试，不直接判测试缺陷 |

### 2.2.2 处理

1. 疑似 flaky 测试不得直接导致验收失败。
2. 必须自动重跑一次。
3. 重跑通过后进入 `flaky_quarantine`。
4. 被隔离测试不得计入正式通过率。
5. 被隔离测试必须记录负责人和关闭期限。

### 2.2.3 禁止事项

1. 禁止把真实失败伪装成 flaky。
2. 禁止无限重跑直到通过。
3. 禁止 reviewer 手动忽略失败测试。

---

## 2.3 行为契约统一执行器

### 2.3.1 目标

行为层契约不能只说“写成 CI 测试”，必须有统一入口。

### 2.3.2 执行器输入

```json
{
  "contract_version": "string",
  "contract_entries": ["access_token.ttl_seconds", "refresh_token.rotation"],
  "target_module": "string",
  "environment_image": "string",
  "timeout_seconds": 600,
  "test_suite_uri": "string"
}
```

### 2.3.3 执行器输出

```json
{
  "status": "passed | failed | timeout | environment_error",
  "results": [
    {
      "contract_entry": "string",
      "passed": true,
      "evidence_uri": "string",
      "failure_fingerprint": "string | null"
    }
  ]
}
```

### 2.3.4 失败归属

| 错误类型 | 归属 |
|---|---|
| 测试环境启动失败 | 环境类 |
| 契约测试生成错误 | 契约/生成器 |
| 新实现违反契约 | 实现方 |
| 契约本身有误 | Checkpoint ③ |

---

## 2.4 Phase 1 搜索完成标准

### 2.4.1 目标

“确认没有”必须有完成标准，不能靠感觉。

### 2.4.2 必查来源

至少包括：

1. 当前代码仓库。
2. 当前依赖树。
3. 内部知识库/文档。
4. 公开包管理器。
5. 已知参考仓库。
6. 开源搜索引擎或代码搜索。

### 2.4.3 查询要求

| 项 | 要求 |
|---|---|
| 关键词变体 | 至少 5 个 |
| 同义词 | 至少 2 组 |
| 时间范围 | 按项目定义，默认近 3 年 |
| 许可初筛 | 必须记录 |
| 失败原因 | 若存在但不适配，必须记录 |

### 2.4.4 停止条件

满足以下之一可停止：

1. 找到可直接用/参考改写候选。
2. 时间盒到期，转“未完成/超时”。
3. 所有必查来源均已查询且无候选。
4. 人工批准提前停止。

### 2.4.5 禁止事项

1. 时间盒超时不得直接判“确认没有”。
2. 验证失败不得降级为“确认没有”。
3. 搜索记录不得缺 `search_trace`。

---

## 2.5 双 Reviewer 隔离

### 2.5.1 独立性要求

双 Reviewer 不得共享以下内容：

1. 对方输出。
2. 对方评分。
3. 对方证据链。
4. 同一轮领导总结。
5. 相同随机种子下的相同提示顺序。

### 2.5.2 推荐配置

| 条件 | 推荐 |
|---|---|
| 模型 | 尽量不同模型或不同档位（**起步期只有 DeepSeek 官方一个 provider** → 落到「同模型不同 effort 档 + 不同提示模板」，别当成已有多厂商交叉） |
| 提示 | 相同评审规则，但不同表达模板 |
| 顺序 | 随机 |
| 温度 | 低温度 |
| 上下文 | 只给验收所需切片 |

### 2.5.3 相关性控制

1. 如果两个 reviewer 长期 100% 一致，必须抽检。
2. 如果所有分歧都被同一方发现，需要检查另一方是否能力不足。
3. 必须记录两个 reviewer 的模型版本和 prompt 版本。

---

## 2.6 复用候选适配矩阵

### 2.6.1 适用场景

Phase 1 中候选结论为：

1. 直接可用。
2. 参考改写。
3. 存在但不适配。

### 2.6.2 适配矩阵

| 维度 | 检查项 | 证据 |
|---|---|---|
| 功能 | 是否覆盖目标能力 | 冒烟测试 |
| 许可 | 是否兼容商用/闭源 | 许可证文本 |
| 依赖 | 是否引入冲突依赖 | 依赖树 |
| 安全 | 是否有已知漏洞 | 扫描报告 |
| 性能 | 是否满足预算 | 基准测试 |
| 维护 | 是否活跃 | 提交记录 |
| 测试 | 原仓库测试是否可复现 | 测试日志 |
| 验收 | 是否覆盖我方验收子集 | 验收 ID 映射 |

### 2.6.3 结论规则

1. 原仓库测试通过只是证据之一。
2. 许可不兼容直接判 `exists_but_incompatible`。
3. 安全高危漏洞未修复直接判 `exists_but_incompatible`。
4. 无法复现测试走豁免审批，不得直接判失败。

---

## 2.7 指纹标定统计要求

### 2.7.1 样本来源

标定不能只用人工注入样本，必须混合：

| 类型 | 比例建议 |
|---|---|
| 人工注入故障 | 30% |
| 历史真实失败 | 50% |
| 跨模块复杂故障 | 20% |

### 2.7.2 最低样本量

1. 起步标定：至少 30 个样本。
2. 正式上线前：至少 100 个样本。
3. 每个故障类别至少 20 个样本。

### 2.7.3 输出要求

必须输出：

1. 混淆矩阵。
2. 准确率。
3. 召回率。
4. 误聚率。
5. 漂移误判率。
6. 95% 置信区间。

### 2.7.4 调参规则

1. 不得只看准确率就调指纹。
2. 卡死 L1 出现时必须优先查粒度过粗。
3. 直冲 L3 升高时必须查粒度过细、任务不适配、环境不稳定。
4. 每次调参必须保留旧规则版本以便回滚。

---

# 第三章 安全、风险与合规

## 3.1 妥协模式风险分级

### 3.1.1 风险等级

| 等级 | 含义 | 是否允许默认妥协 |
|---|---|---|
| low | 不影响安全/数据/资金 | 允许 |
| medium | 影响维护性或非核心行为 | 允许，但必须登记 |
| high | 影响认证、权限、数据一致性 | 禁止默认妥协 |
| critical | 影响支付、生产配置、隐私、不可逆操作 | 禁止妥协，直接人工 |

### 3.1.2 高危域禁用清单

以下模块禁止默认落妥协模式：

1. 认证。
2. 授权。
3. 支付。
4. 数据迁移。
5. 生产配置。
6. 密钥管理。
7. 审计日志。
8. 回滚脚本。
9. 隐私数据处理。
10. 安全中间件。

### 3.1.3 高危域处理

高危域出现指纹漂移：

```text
默认不进入妥协模式 → 进入 L2 顾问或升级 L3
```

---

## 3.2 技术债闭环

### 3.2.1 技术债记录字段

```json
{
  "debt_id": "string",
  "module_path": "string",
  "task_id": "string",
  "owner": "string",
  "created_at": "ISO8601",
  "due_date": "date",
  "risk_level": "low | medium | high | critical",
  "ticket_id": "string",
  "status": "open | in_progress | closed | waived",
  "blocking_rewrite": true
}
```

### 3.2.2 阻断规则

1. 未关闭技术债可阻断该模块进入受控重写。
2. 高风险以上技术债必须阻断新增功能。
3. 逾期技术债必须升级人工。
4. 豁免必须记录批准人和有效期。

---

## 3.3 密钥治理

### 3.3.1 基本原则

1. 禁止长期密钥直接注入 worker。
2. 禁止密钥出现在日志、摘要、错误信息中。
3. 禁止密钥写入普通产物目录。
4. 优先使用临时凭据。
5. 最小权限原则。

### 3.3.2 注入方式

| 场景 | 推荐 |
|---|---|
| 本地测试 | 临时环境变量 + 自动过期 |
| 云服务 | 短期 token |
| 数据库 | 只读账号或限定 schema |
| 部署 | 专用部署身份 |

### 3.3.3 审计

每次密钥使用必须记录：

1. 任务 ID。
2. worker ID。
3. 权限范围。
4. 使用时间。
5. 是否产生副作用。

---

## 3.4 高风险操作审批

### 3.4.1 高风险操作清单

1. 删除数据。
2. 修改生产配置。
3. 发布生产。
4. 修改权限。
5. 迁移生产数据。
6. 销毁环境。
7. 修改密钥。
8. 修改契约并重新冻结。
9. 强制解锁。
10. 跳过验收。

### 3.4.2 审批要求

| 操作 | 要求 |
|---|---|
| 生产发布 | 人工批准 + 回滚点 |
| 数据删除 | 人工批准 + 备份 |
| 权限变更 | 人工批准 + 审计 |
| 配置变更 | dry-run + 人工批准 |
| 强制解锁 | 人工批准 + 现场保存 |

### 3.4.3 禁止事项

1. 禁止 LLM 自行批准高风险操作。
2. 禁止无 dry-run 直接执行生产变更。
3. 禁止无回滚点部署。

---

## 3.5 供应链与许可证

### 3.5.1 许可证策略

| 类别 | 处理 |
|---|---|
| MIT / Apache-2.0 / BSD | 通常可用 |
| GPL / AGPL | 必须人工审批 |
| 未知许可 | 禁止采用 |
| 无许可证 | 禁止采用 |
| 商业组件 | 按采购流程 |

### 3.5.2 依赖检查

每个外部依赖必须检查：

1. 许可证。
2. 最近更新时间。
3. 已知漏洞。
4. 维护者可信度。
5. 是否与现有依赖冲突。

### 3.5.3 采用记录

所有采用代码必须记录：

```json
{
  "source": "url",
  "license": "string",
  "commit": "string",
  "security_scan": "string",
  "approval": "auto | human",
  "used_in": ["path"]
}
```

---

## 3.6 日志脱敏与保留

### 3.6.1 日志分级

| 级别 | 内容 | 访问 |
|---|---|---|
| public | 指标、状态 | 项目组 |
| internal | 普通日志 | 开发 |
| sensitive | 含用户数据/密钥片段 | 受限 |
| audit | 人工审批/安全事件 | 审计 |

### 3.6.2 脱敏规则

必须脱敏：

1. API key。
2. token。
3. 密码。
4. 私钥。
5. 用户手机号。
6. 邮箱。
7. 身份证号。
8. 数据库连接串。
9. 云凭据。

### 3.6.3 保留期

| 日志类型 | 建议保留 |
|---|---|
| 普通运行日志 | 30 天 |
| 审计日志 | 180 天以上 |
| 安全事件 | 365 天以上 |
| 任务产物日志 | 随任务归档 |

---

# 第四章 交付工程

## 4.1 契约版本兼容策略

### 4.1.1 版本号

契约必须使用语义化版本：

```text
major.minor.patch
```

### 4.1.2 兼容规则

| 变更 | 版本变化 | 处理 |
|---|---|---|
| 新增可选字段 | minor | 向后兼容 |
| 修改字段类型 | major | 不兼容 |
| 删除字段 | major | 不兼容 |
| 修改枚举值含义 | major | 不兼容 |
| 修改行为约束 | minor/major | 按影响判断 |

### 4.1.3 锁定规则

1. 每个任务必须锁定契约版本。
2. 跨批次模块必须使用同一契约版本。
3. 契约升级不得自动影响运行中任务。
4. 不兼容升级必须走 Checkpoint ③。

---

## 4.2 分支 / Worktree 与合并策略

### 4.2.1 工作区

每个模块必须有独立工作区：

```text
workspaces/task_id/module_id/
```

推荐使用：

1. `git worktree`
2. 独立分支
3. 独立临时目录
4. 独立构建产物目录

### 4.2.2 分支命名

```text
task/{task_id}/{module_id}
```

### 4.2.3 提交粒度

每个提交必须满足：

1. 只属于一个模块。
2. 可独立回滚。
3. 有对应任务 ID。
4. 有对应验收项 ID。

### 4.2.4 合并顺序

1. 先合并无依赖模块。
2. 再合并下游模块。
3. 契约相关模块必须通过类型层和行为层检查。
4. 冲突必须由明确 owner 处理。

### 4.2.5 合并失败

1. 保留原分支。
2. 不得强推。
3. 必须记录失败原因。
4. 可回滚到合并前检查点。

---

## 4.3 常规交付回滚

### 4.3.1 回滚点

每次副作用前必须创建回滚点：

| 操作 | 回滚点 |
|---|---|
| 代码合并 | commit hash |
| 数据库迁移 | migration version + backup |
| 部署 | image tag / release id |
| 配置变更 | config snapshot |
| 数据清洗 | 原始快照或反向补丁 |

### 4.3.2 回滚要求

1. 每个部署必须有回滚命令或步骤。
2. 数据迁移必须有备份或补偿脚本。
3. 配置变更必须能一键恢复。
4. 回滚必须演练过一次，或至少有明确验证步骤。

---

## 4.4 数据迁移一致性

### 4.4.1 迁移协议

数据迁移必须包含：

1. 事务边界。
2. 批次大小。
3. 校验和。
4. 断点。
5. 重放策略。
6. 回滚策略。
7. 隐私处理。

### 4.4.2 推荐流程

```text
备份 → 干跑 → 小批迁移 → 校验 → 全量迁移 → 二次校验 → 观察期 → 完成
```

### 4.4.3 校验项

| 校验 | 说明 |
|---|---|
| 行数 | 源/目标行数一致或可解释 |
| 主键 | 无重复 |
| 外键 | 引用完整 |
| 校验和 | 关键字段一致 |
| 空值 | 非空约束满足 |
| 枚举 | 值合法 |

### 4.4.4 禁止事项

1. 禁止无备份迁移。
2. 禁止不可回放的迁移脚本。
3. 禁止迁移中途静默改字段映射。
4. 禁止生产数据直接给普通 worker。

---

## 4.5 非 Token 成本账本

### 4.5.1 成本项

| 成本项 | 说明 |
|---|---|
| token | 模型调用 |
| tool_call | 工具调用次数 |
| ci_time | CI/测试时间 |
| cloud_resource | 容器/云资源 |
| human_review | 人工审批/评审 |
| waiting | 等待人工或环境的时间 |
| storage | 产物存储 |

### 4.5.2 记账事件

```json
{
  "cost_id": "uuid",
  "task_id": "string",
  "phase": "string",
  "module_id": "string | null",
  "cost_type": "token | tool_call | ci_time | cloud_resource | human_review | waiting | storage",
  "amount": 0,
  "unit": "string",
  "unit_price": 0,
  "total": 0,
  "timestamp": "ISO8601"
}
```

### 4.5.3 ROI 实测

结案实测 ROI 必须使用：

```text
实际人工节省收益 ÷ 实际总成本
```

实际总成本包括：

1. 实际 token。
2. 工具调用。
3. 云资源。
4. CI 时间。
5. 人工评审。
6. 等待成本。

不得继续使用立项预估分母。

---

## 4.6 产物 Manifest 与哈希

### 4.6.1 每个交付任务必须有 manifest

```json
{
  "task_id": "string",
  "created_at": "ISO8601",
  "process_doc_version": "string",
  "contract_version": "string",
  "artifacts": [
    {
      "path": "string",
      "sha256": "string",
      "kind": "code | doc | log | config | migration | rollback_plan",
      "source": "worker | ci | human",
      "required": true
    }
  ],
  "test_reports": ["uri"],
  "review_verdicts": ["uri"],
  "checkpoint_approvals": ["uri"]
}
```

### 4.6.2 校验规则

1. 摘要必须能从落盘文件重新计算哈希。
2. 领导只看摘要时，必须能追溯到完整产物。
3. 缺少必要产物不得进入 `delivered`。
4. manifest 必须归档。

---

## 4.7 取消、暂停与优先级

### 4.7.1 操作定义

| 操作 | 含义 |
|---|---|
| cancel | 终止任务，不再继续 |
| pause | 暂停任务，可恢复 |
| resume | 恢复任务 |
| preempt | 高优先级任务抢占资源 |

### 4.7.2 安全终止流程

1. 停止派发新任务。
2. 等待运行中工具调用进入安全点。
3. 保存现场。
4. 释放锁。
5. 写入终止原因。
6. 对已产生副作用检查回滚。

### 4.7.3 优先级规则

1. 生产事故修复优先。
2. 安全修复优先。
3. 已完成大半的任务不轻易抢占。
4. 抢占必须记录成本损失。
5. 抢占不得导致静默丢失产物。

---

## 4.8 行为契约 DSL 与生成边界

### 4.8.1 能力边界

契约自动生成适合：

1. 类型结构。
2. 字段必填性。
3. 枚举范围。
4. 基本请求/响应格式。
5. 简单数值范围。

不完全适合：

1. 幂等性。
2. 轮换语义。
3. 安全语义。
4. 状态机。
5. 跨服务事务。
6. 性能约束。
7. 复杂业务时序。

### 4.8.2 人工审核

以下行为契约必须人工审核：

1. 认证。
2. 授权。
3. 支付。
4. 数据迁移。
5. 回滚。
6. 审计。
7. 任何不可逆操作。

### 4.8.3 禁止事项

1. 禁止声称行为契约完全自动生成。
2. 禁止未审核的行为契约直接进入生产验收。
3. 禁止手写替代白测试而不记录豁免。

---

# 第五章 变更控制

## 5.1 验收清单变更控制

### 5.1.1 变更触发

以下情况可触发验收清单变更：

1. Phase 0 需求写错。
2. 发现遗漏验收项。
3. 契约变更。
4. 法规/安全要求变化。
5. 人工审批要求补充。

### 5.1.2 变更流程

```text
提出变更 → 影响分析 → 人工审批 → 版本号递增 → 重新覆盖性 diff → 重验受影响模块
```

### 5.1.3 影响分析必须包含

1. 哪些 brief 受影响。
2. 哪些模块需要重验。
3. 哪些契约条目受影响。
4. 预算是否变化。
5. 是否需要重新 Checkpoint ①。

### 5.1.4 禁止事项

1. 禁止执行中静默追加验收项。
2. 禁止删除验收项不留审计。
3. 禁止已派发 brief 自动继承新验收清单。
4. 禁止变更验收清单不递增版本。

---

# 第六章 规则单一事实源与插件硬拦截

本章对应框架级第 4 项的工程落地：  
将可执行硬规则收敛为版本化规则文件，并通过插件层执行 `approve / modify / block`。

## 6.1 单一事实源目标

以下规则必须逐步从文档、prompt、代码三处重复，收敛到一个机器可读规则源：

1. `max_workers`
2. `max_tool_calls_per_worker`
3. `token_fuse_ratio`
4. `brief_rewrite_auto_limit`
5. `brief_rewrite_total_limit`
6. `environment_retry_backoff`
7. `checkpoint_timeout_actions`
8. `forbidden_commands`
9. `high_risk_domains`
10. `budget_borrow_limit_ratio`

## 6.2 rules.json 最小结构

```json
{
  "version": "rules@2026-xx-xx",
  "hard_limits": {
    "max_workers": 1,
    "max_tool_calls_per_worker": 15,
    "token_fuse_ratio": 1.2,
    "brief_rewrite_auto_limit": 1,
    "brief_rewrite_total_limit": 2,
    "budget_borrow_limit_ratio": 0.5
  },
  "retry": {
    "environment_backoff_seconds": [1, 4, 16],
    "jitter": true,
    "total_retry_limit_seconds": 300,
    "retryable_error_whitelist": ["ETIMEDOUT", "ECONNRESET", "SERVICE_UNAVAILABLE"]
  },
  "security": {
    "forbidden_commands": ["rm -rf /", "curl | sh"],
    "high_risk_domains": [
      "auth", "permission", "payment", "data_migration", "prod_config",
      "secret_management", "audit_logging", "rollback_script",
      "privacy_data", "security_middleware"
    ],
    "high_risk_domain_matching": {
      "match_mode": "any",
      "case_sensitive": false,
      "rules": {
        "auth": {"paths": ["**/auth/**", "**/login/**", "**/session/**"], "keywords": ["auth", "jwt", "login", "session", "credential"]},
        "permission": {"paths": ["**/permission/**", "**/rbac/**", "**/acl/**"], "keywords": ["permission", "rbac", "acl", "authorize", "role"]},
        "payment": {"paths": ["**/payment/**", "**/billing/**", "**/checkout/**"], "keywords": ["payment", "billing", "checkout", "refund", "invoice"]},
        "data_migration": {"paths": ["**/migrations/**", "**/migrate/**"], "keywords": ["migration", "migrate", "backfill"]},
        "prod_config": {"paths": ["**/config/prod*/**", "**/*.prod.yaml"], "keywords": ["prod_config", "production_config"]},
        "secret_management": {"paths": ["**/secret*/**", "**/keyring/**", "**/vault/**"], "keywords": ["secret", "keyring", "vault", "private_key", "api_key"]},
        "audit_logging": {"paths": ["**/audit/**"], "keywords": ["audit_log", "auditlog", "audit_trail"]},
        "rollback_script": {"paths": ["**/rollback*/**", "**/*rollback*.sh"], "keywords": ["rollback", "revert", "downgrade_script"]},
        "privacy_data": {"paths": ["**/pii/**", "**/privacy/**"], "keywords": ["pii", "privacy", "gdpr", "personal_data", "phone", "id_card"]},
        "security_middleware": {"paths": ["**/middleware/security*/**", "**/security/**"], "keywords": ["security_middleware", "csrf", "xss", "rate_limit", "waf"]}
      }
    }
  },
  "checkpoints": {
    "sla_high_risk_hours": 4,
    "sla_normal_hours": 24,
    "timeout_high_risk_action": "reject_and_hold",
    "timeout_normal_action": "hold_safe_state"
  }
}
```

### 6.2.1 高危域清单的权威源与启动自检

`high_risk_domains` 的唯一权威源是 **3.1.2 的 10 项清单**；`high_risk_domains` 与
`high_risk_domain_matching.rules` 的键集合必须**完全相等**。
清单不全属「静默放行」故障——规则文件存在、解析成功、插件照常 approve，不触发任何告警，
6.4 的 fail-closed 结构上挡不住它，故插件加载时必须做启动自检：

```python
CANONICAL = {
    "auth", "permission", "payment", "data_migration", "prod_config",
    "secret_management", "audit_logging", "rollback_script",
    "privacy_data", "security_middleware",
}

def self_check(rules):
    declared = set(rules["security"]["high_risk_domains"])
    matched = set(rules["security"]["high_risk_domain_matching"]["rules"].keys())
    if declared != matched:
        raise RuleConfigError(f"高危域清单与匹配规则不一致: {declared ^ matched}")
    if declared != CANONICAL:
        raise RuleConfigError(f"高危域清单缺失: {CANONICAL - declared}")
```

日后若有人把清单改回 5 项，进程当场起不来，而不是静默放行。

【需确认】`high_risk_domain_matching` 的路径/关键词是通用示例，真实项目须按目录结构重写；
匹配规则配不全等于清单又少一截，建议先用真实代码库跑一遍命中率再定稿。

## 6.3 插件动作定义

| 动作 | 含义 |
|---|---|
| approve | 放行 |
| modify | 修改参数或命令后放行 |
| block | 阻断 |

### 6.3.1 返回结构

```json
{
  "action": "approve | modify | block",
  "message": "string",
  "modified_payload": {},
  "rule_id": "string",
  "rules_version": "string"
}
```

## 6.4 Fail-Closed 规则

插件必须默认失败关闭。

```text
插件异常 → block
规则文件缺失 → block
规则文件解析失败 → block
无法确认规则版本 → block
```

禁止：

```text
插件异常 → approve
```

## 6.5 启用与热更

| 对象 | 规则 |
|---|---|
| 插件启用 | 首次启用需重启进程 |
| 插件禁用 | 需重启或明确热禁用接口 |
| rules.json | 可热更 |
| 规则缓存 | 必须加锁 |
| 规则版本 | 每次拦截必须记录 |

推荐实现：

1. 每次工具调用现读 `rules.json`。
2. 若使用缓存，必须使用读写锁。
3. 文件变更后必须刷新缓存或版本号。

## 6.6 并发安全

1. 工具并行运行时，插件会并发触发。
2. 共享规则缓存必须加读写锁。
3. 禁止在并发下写坏缓存。
4. 禁止读取半写入状态的规则文件。

## 6.7 覆盖边界

| 层 | 拦截方式 |
|---|---|
| 工具调用 | `pre_tool_call` |
| 模型输出 | `pre_verify` 或等价校验 |
| 文件写入 | 文件系统权限 + 写入白名单 |
| 预算 | Code 层预算计数器 |
| 状态迁移 | 状态机校验 |

## 6.8 插件回归用例

每次修改规则插件后必须运行回归用例。

### 6.8.1 用例环境

1. 临时 `HOME`。
2. 隔离配置目录。
3. 测试插件。
4. 测试规则文件。
5. 断言脚本。

### 6.8.2 最小断言

| 用例 | 断言 |
|---|---|
| block | 命中禁词时工具不执行，返回拦截错误 |
| modify | 原始命令被替换，实际执行修改后命令 |
| approve | 正常命令放行 |
| fail_closed | 插件异常时返回 block |
| hot_reload | 修改规则后无需重启即可生效 |
| concurrency | 并发调用下规则不串、不漏 |
| no_plugin | 无插件时门控跳过，不影响正常执行 |
| high_risk_domains_complete | 3.1.2 全量 10 项命中时均判高危，不得落默认妥协 |
| high_risk_domains_consistency | `high_risk_domains` 与 `high_risk_domain_matching.rules` 键集合完全相等 |
| pragma_applied | 新连接建立后 `journal_mode=wal`、`busy_timeout=5000`、`foreign_keys=1` |
| concurrent_write | 2 并发写者各写 50 次不抛 `SQLITE_BUSY`，最终计数 = 100 |
| busy_snapshot_retry | 人为制造 read-then-write 冲突，重试机制生效而非直接失败 |
| txn_atomicity | 中途抛异常时状态更新与审计日志同时回滚 |

### 6.8.3 回归通过标准

```text
所有断言通过，且日志中可看到规则版本与动作。
```

---

# 第七章 工程验收清单

## 7.1 状态机验收

- [ ] 所有状态枚举已落库。
- [ ] 所有状态迁移都有日志。
- [ ] 非法状态迁移会被拒绝。
- [ ] 重启后可恢复到稳定检查点。
- [ ] 不会重复执行非幂等副作用。

## 7.2 锁与并发验收

- [ ] 文件锁可物理互斥。
- [ ] 资源锁覆盖数据库/端口/环境。
- [ ] 锁超时可回收。
- [ ] 崩溃后锁不会永久泄漏。
- [ ] 强制解锁有审计。

## 7.3 预算验收

- [ ] 单任务超 120% 会进入 `paused_for_budget`。
- [ ] 全局池耗尽会进入 `circuit_broken`。
- [ ] 借调不超过 50%。
- [ ] 借调事件进入 Checkpoint 汇报队列。
- [ ] 非 token 成本可归集。

## 7.4 验收流程验收

- [ ] Reviewer verdict 可机器比对。
- [ ] 空报告规则按“未执行检查”判定。
- [ ] 高危阻断项不走子集容忍。
- [ ] 双 Reviewer 独立隔离。
- [ ] Checkpoint 有 SLA 和超时动作。（起步期不适用：无计时器，改查「待办里有记录且每日提醒可达」；SLA 回填条件见流程文档第九节。）

## 7.5 安全验收

- [ ] 高危域禁止默认妥协。
- [ ] 技术债有 owner、期限、阻断规则。
- [ ] 密钥不进日志。
- [ ] 高风险操作有审批。
- [ ] 外部依赖有许可与安全记录。

## 7.6 插件硬拦截验收

- [ ] `rules.json` 版本可追踪。
- [ ] 插件支持 `approve / modify / block`。
- [ ] 插件异常时 fail-closed。
- [ ] 规则热更可用。
- [ ] 并发调用安全。
- [ ] 回归用例全部通过。

---

# 附录 A：最小状态迁移审计表

```sql
CREATE TABLE state_transitions (
  id INTEGER PRIMARY KEY,
  entity_type TEXT NOT NULL,
  entity_id TEXT NOT NULL,
  from_state TEXT NOT NULL,
  to_state TEXT NOT NULL,
  phase_from TEXT,
  phase_to TEXT,
  reason_code TEXT NOT NULL,
  actor TEXT NOT NULL,
  evidence_uri TEXT,
  created_at TEXT NOT NULL
);
```

# 附录 B：最小锁表

```sql
CREATE TABLE locks (
  lock_key TEXT PRIMARY KEY,
  lock_type TEXT NOT NULL,
  lock_mode TEXT NOT NULL,
  owner_id TEXT NOT NULL,
  task_id TEXT NOT NULL,
  acquired_at TEXT NOT NULL,
  lease_expires_at TEXT NOT NULL,
  state TEXT NOT NULL
);
```

# 附录 C：最小成本账本表

```sql
CREATE TABLE cost_ledger (
  cost_id TEXT PRIMARY KEY,
  task_id TEXT NOT NULL,
  phase TEXT,
  module_id TEXT,
  cost_type TEXT NOT NULL,
  amount REAL NOT NULL,
  unit TEXT NOT NULL,
  unit_price REAL,
  total REAL,
  created_at TEXT NOT NULL
);
```

# 附录 D：插件伪代码

```python
def pre_tool_call(tool_name, payload, context):
    try:
        rules = load_rules_with_lock()

        if rules.is_forbidden(tool_name, payload):
            return {
                "action": "block",
                "message": "blocked by rules",
                "rule_id": rules.matched_rule_id,
                "rules_version": rules.version
            }

        if rules.should_rewrite(tool_name, payload):
            new_payload = rules.rewrite(payload)
            return {
                "action": "modify",
                "modified_payload": new_payload,
                "rule_id": rules.matched_rule_id,
                "rules_version": rules.version
            }

        return {
            "action": "approve",
            "rules_version": rules.version
        }

    except Exception as e:
        return {
            "action": "block",
            "message": f"plugin failure: fail-closed: {e}",
            "rules_version": "unknown"
        }
```

# 附录 E：回归用例骨架

```text
1. 创建临时 HOME
2. 写入测试插件
3. 写入测试 rules.json
4. 启动隔离环境
5. 断言 block 用例
6. 断言 modify 用例
7. 断言 approve 用例
8. 断言插件异常时 fail-closed
9. 断言规则热更生效
10. 断言并发调用无串规则
11. 断言无插件时门控跳过（no_plugin）
12. 输出测试报告
```

---

## 结尾说明

本手册 v0.3.0 覆盖：

1. 流程文档 v2.4.4 定稿说明中的「C 组 28 项」工程缺口（口径见流程文档 L763）。
2. 框架级第 4 项“单一事实源 + 插件硬拦截”的落地方案。
3. 流程文档中所有“由 Code 层执行”的硬边界所需的最小工程规格。

本手册不改变流程文档的业务规则。  
后续如果流程文档升级到新版本，本手册必须同步进行回归验证。
