🏠

深度验证 (Deep Validation)

概述

想象你正在维护一个庞大的任务管理系统,其中包含成千上万的 Issue、依赖关系、Epic 层级结构、Agent Bead 元数据,以及复杂的 Molecule 组合。随着时间推移,数据会"腐烂"——删除的 Issue 留下的悬空依赖、状态不一致的 Agent、结构破损的 Molecule。深度验证模块就是这个系统的"核磁共振成像仪":它不满足于表面健康检查,而是深入数据库内部,逐层扫描 Issue 图的语义完整性,发现那些普通查询无法察觉的结构性问题。

这个模块存在的根本原因是:引用完整性无法仅靠数据库外键约束保证。Beads 系统使用 Dolt(版本化 SQL 数据库)存储 Issue 和依赖关系,但依赖关系是应用层语义(如 parent-childblocksattests 等),而非数据库 schema 强制的外键。当 Issue 被删除、迁移或合并时,依赖记录可能残留,形成"僵尸引用"。深度验证通过执行一系列语义感知的 SQL 查询,系统性地发现并报告这些问题,为后续的自动修复提供精确的诊断输入。

架构设计

flowchart TB subgraph Entry["入口层"] RunDeepValidation["RunDeepValidation
协调所有检查"] end subgraph Checks["验证检查器"] ParentConsistency["checkParentConsistency
父子关系完整性"] DependencyIntegrity["checkDependencyIntegrity
依赖引用完整性"] EpicCompleteness["checkEpicCompleteness
Epic 完成度检测"] AgentBeadIntegrity["checkAgentBeadIntegrity
Agent 元数据验证"] MailThreadIntegrity["checkMailThreadIntegrity
邮件线程引用验证"] MoleculeIntegrity["checkMoleculeIntegrity
Molecule 结构验证"] end subgraph Data["数据层"] DoltDB["Dolt 数据库
issues / dependencies 表"] ConfigFile["config.json
后端类型检测"] end subgraph Output["输出层"] DeepValidationResult["DeepValidationResult
结构化诊断报告"] PrintFunc["PrintDeepValidationResult
人类可读输出"] JSONFunc["DeepValidationResultJSON
机器可读输出"] end Entry --> ParentConsistency Entry --> DependencyIntegrity Entry --> EpicCompleteness Entry --> AgentBeadIntegrity Entry --> MailThreadIntegrity Entry --> MoleculeIntegrity ParentConsistency --> DoltDB DependencyIntegrity --> DoltDB EpicCompleteness --> DoltDB AgentBeadIntegrity --> DoltDB MailThreadIntegrity --> DoltDB MoleculeIntegrity --> DoltDB Entry --> ConfigFile ParentConsistency --> DeepValidationResult DependencyIntegrity --> DeepValidationResult EpicCompleteness --> DeepValidationResult AgentBeadIntegrity --> DeepValidationResult MailThreadIntegrity --> DeepValidationResult MoleculeIntegrity --> DeepValidationResult DeepValidationResult --> PrintFunc DeepValidationResult --> JSONFunc

数据流 walkthrough

  1. 入口协调RunDeepValidation(path) 接收 beads 仓库路径,首先通过 配置文件 检测后端类型(Dolt vs SQLite)。只有 Dolt 后端才执行深度验证,因为 SQLite 后端使用不同的 schema。

  2. 数据库连接:解析 .beads 目录重定向,打开 Dolt SQL 连接。这里使用标准 database/sql 接口,而非 Dolt 专有 API,保持与 存储层 的松耦合。

  3. 并行无关的检查序列:六个检查函数按固定顺序执行,每个都是独立的 SQL 查询。它们之间没有数据依赖,但共享同一个数据库连接。这种设计牺牲了潜在的并行性,换取了实现简单性和错误隔离——单个检查失败不会阻塞其他检查。

  4. 结果聚合:每个检查返回一个 DoctorCheck 结构(定义在 诊断核心),包含状态(OK/Warning/Error)、消息、详情和修复建议。RunDeepValidation 聚合所有检查结果,计算 OverallOK 标志,并填充 TotalIssuesTotalDependencies 用于进度报告。

  5. 输出分发:调用者可选择人类可读的 PrintDeepValidationResult(CLI 输出)或机器可读的 DeepValidationResultJSON(供其他工具消费,如 MCP 集成)。

组件深度解析

DeepValidationResult 结构

设计意图:作为深度验证的"诊断报告单",这个结构将所有检查结果打包成一个可序列化、可聚合的单元。它采用结果对象模式(Result Object Pattern),而非通过返回值 + 错误码的传统方式,原因是:

  • 需要同时返回多个独立检查的结果(不是单一成功/失败)
  • 需要保留每个检查的详细信息(消息、详情、修复建议)
  • 需要支持 JSON 序列化供外部工具消费
type DeepValidationResult struct {
    ParentConsistency   DoctorCheck   `json:"parent_consistency"`
    DependencyIntegrity DoctorCheck   `json:"dependency_integrity"`
    EpicCompleteness    DoctorCheck   `json:"epic_completeness"`
    AgentBeadIntegrity  DoctorCheck   `json:"agent_bead_integrity"`
    MailThreadIntegrity DoctorCheck   `json:"mail_thread_integrity"`
    MoleculeIntegrity   DoctorCheck   `json:"molecule_integrity"`
    AllChecks           []DoctorCheck `json:"all_checks"`
    TotalIssues         int           `json:"total_issues"`
    TotalDependencies   int           `json:"total_dependencies"`
    OverallOK           bool          `json:"overall_ok"`
}

字段语义

  • 六个具名字段:每个对应一个检查函数,便于代码直接访问特定检查结果(如 if result.ParentConsistency.Status == StatusError { ... }
  • AllChecks 切片:冗余存储所有检查,便于迭代输出和 JSON 序列化时保持数组顺序
  • TotalIssues / TotalDependencies:元数据,用于在输出中显示扫描范围("Scanned: 1234 issues, 5678 dependencies"),帮助用户理解检查的覆盖度
  • OverallOK:快速判断标志,由协调逻辑在聚合时计算(任何检查返回 Error 即为 false)

设计权衡:这里存在冗余 vs 便利的张力。AllChecks 与六个具名字段内容重复,但这种设计:

  • ✅ 优点:支持两种访问模式——按名称直接访问(类型安全)和迭代访问(便于输出循环)
  • ❌ 缺点:如果未来添加新检查,需要同时更新具名字段和聚合逻辑,存在不一致风险

RunDeepValidation 函数

职责:深度验证的编排器(Orchestrator)。它不执行具体检查逻辑,而是负责:

  1. 环境探测(后端类型、数据库存在性)
  2. 资源管理(数据库连接打开/关闭)
  3. 检查调度(按顺序调用六个检查函数)
  4. 结果聚合(收集检查结果,计算总体状态)

关键设计决策

1. 后端类型门控

if backend != configfile.BackendDolt {
    // 返回 Warning,建议迁移到 Dolt
    return result
}

深度验证仅支持 Dolt 后端。这是因为检查逻辑依赖 Dolt 的特定 schema(如 issues 表、dependencies 表、notes JSON 字段)。SQLite 后端使用不同的数据结构,强行执行会导致 SQL 错误。这里选择显式拒绝而非静默跳过,通过返回 Warning 引导用户迁移到推荐的后端。

2. 优雅降级策略

_ = db.QueryRow("SELECT COUNT(*) FROM issues").Scan(&result.TotalIssues)
// 注释:Best effort: zero counts are safe defaults for diagnostic display

计数查询失败不会中断验证流程。这是诊断工具的核心设计原则:尽可能多地报告信息,即使部分数据不可用。零计数是安全的默认值,仅影响输出美观,不影响检查逻辑。

3. 错误传播模式

result.ParentConsistency = checkParentConsistency(db)
result.AllChecks = append(result.AllChecks, result.ParentConsistency)
if result.ParentConsistency.Status == StatusError {
    result.OverallOK = false
}

每个检查独立执行,错误不传播(不 return),而是通过 Status 字段标记。OverallOK 在所有检查完成后反映整体健康状态。这种设计允许部分成功——即使某些检查失败,用户仍能获得其他检查的结果。

checkParentConsistency 函数

问题空间:父子依赖(parent-child 类型)是 Beads 系统的核心抽象,用于构建 Issue 层级树(如 Epic → Story → Task)。当子 Issue 或父 Issue 被删除时,依赖记录可能残留,形成"孤儿依赖"。

SQL 策略

SELECT d.issue_id, d.depends_on_id
FROM dependencies d
WHERE d.type = 'parent-child'
  AND (
    NOT EXISTS (SELECT 1 FROM issues WHERE id = d.issue_id)
    OR NOT EXISTS (SELECT 1 FROM issues WHERE id = d.depends_on_id)
  )
LIMIT 10

使用 NOT EXISTS 而非 LEFT JOIN ... WHERE ... IS NULL 的原因是:

  • 性能NOT EXISTS 在找到第一个匹配项后即可短路,适合"存在性检查"场景
  • 语义清晰:直接表达"不存在对应的 Issue"这一意图
  • LIMIT 保护:限制返回 10 条,避免在大规模数据损坏时查询阻塞或输出爆炸

输出策略:仅展示前 3 个示例(orphanedDeps[:min(3, len(orphanedDeps))]),而非全部。这是用户体验权衡

  • ✅ 避免终端输出被数百条错误淹没
  • ✅ 提供足够样本让用户理解问题性质
  • ❌ 用户无法从输出中获知完整修复范围(需依赖 bd doctor --fix 自动处理)

checkDependencyIntegrity 函数

checkParentConsistency 的区别

维度 ParentConsistency DependencyIntegrity
检查范围 parent-child 类型 所有依赖类型
严重性 Error Error
修复命令 bd doctor --fix bd repair-deps

设计洞察:为什么需要两个独立的检查?因为 parent-child结构性依赖(影响 Issue 树遍历、Molecule 展开等核心逻辑),而其他依赖类型(如 blocksattests)是语义性依赖(主要用于查询和展示)。分开检查允许:

  1. 更精确的错误分类(用户知道是层级结构问题还是一般依赖问题)
  2. 不同的修复策略(父子依赖可能需要特殊处理)

checkEpicCompleteness 函数

独特之处:这是唯一一个返回 StatusWarning 而非 StatusError 的检查。原因是:

  • 不是数据损坏:Epic 的所有子 Issue 已关闭,但 Epic 本身未关闭,这是状态不一致,而非引用完整性问题
  • 建议性而非强制性:系统可以正常运行,但用户可能希望关闭已完成的 Epic 以保持看板整洁

SQL 聚合逻辑

SELECT e.id, e.title,
       COUNT(c.id) as total_children,
       SUM(CASE WHEN c.status = 'closed' THEN 1 ELSE 0 END) as closed_children
FROM issues e
JOIN dependencies d ON d.depends_on_id = e.id AND d.type = 'parent-child'
JOIN issues c ON c.id = d.issue_id
WHERE e.issue_type = 'epic'
  AND e.status != 'closed'
GROUP BY e.id
HAVING total_children > 0 AND total_children = closed_children
LIMIT 20

这个查询的核心是 HAVING 子句:筛选出"子 Issue 总数 = 已关闭子 Issue 数"的 Epic。使用 SUM(CASE ...) 而非 COUNT(IF ...) 是为了兼容不同 SQL 方言。

checkAgentBeadIntegrity 函数

最复杂的检查:涉及 JSON 解析、schema 探测、回退策略。

Schema 探测

var hasNotes bool
err := db.QueryRow(`
    SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'issues' AND COLUMN_NAME = 'notes'
`).Scan(&hasNotes)

为什么需要探测notes 字段是可选的,用于存储 Agent Bead 的元数据(role_beadagent_staterole_type)。旧版本 schema 或手动创建的数据库可能没有这个字段。直接查询会导致 SQL 错误。

JSON 提取与回退

query := `
    SELECT id, title,
           COALESCE(JSON_UNQUOTE(JSON_EXTRACT(notes, '$.role_bead')), '') as role_bead,
           ...
    FROM issues
    WHERE issue_type = 'agent'
    LIMIT 100`

rows, err := db.Query(query)
if err != nil {
    // 回退到不提取 JSON 的简化查询
    query = `SELECT id, title, '', '', '' FROM issues WHERE issue_type = 'agent' LIMIT 100`
    rows, err = db.Query(query)
    ...
}

双重回退策略

  1. 首先尝试完整 JSON 提取(获取所有元数据字段)
  2. 如果失败(可能是 JSON 函数不支持或 notes 列不存在),回退到仅获取 idtitle
  3. 如果仍失败,返回 OK("No agent beads found")

这种设计体现了诊断工具的鲁棒性优先:宁可少报告,也不要因自身错误中断流程。

AgentState 验证

state := types.AgentState(agent.AgentState)
if !state.IsValid() {
    invalidAgents = append(invalidAgents, fmt.Sprintf("%s (invalid state: %s)", agent.ID, agent.AgentState))
}

这里依赖 核心领域类型 中的 AgentState.IsValid() 方法。这是一个跨模块契约:深度验证假设 AgentState 枚举定义了所有合法状态,任何不在枚举中的值都是损坏数据。

checkMailThreadIntegrity 函数

特定领域检查:验证 dependencies.thread_id 字段引用的 Issue 是否存在。这个字段用于将依赖关系与邮件线程关联(Beads 的邮件集成功能)。

与一般依赖检查的区别

  • thread_id可选引用(可以为空),而非必需外键
  • 仅当 thread_id != '' AND thread_id IS NOT NULL 时才检查
  • 返回 StatusWarning 而非 Error(因为不影响核心功能)

聚合统计

SELECT d.thread_id, COUNT(*) as refs
...
GROUP BY d.thread_id

thread_id 分组统计引用次数,帮助用户理解影响范围(一个孤儿线程可能被多个依赖引用)。

checkMoleculeIntegrity 函数

最复杂的结构验证:Molecule 是 Beads 的核心抽象,代表可组合的工作单元。一个 Molecule 由多个 Bead 通过 parent-child 依赖组成 DAG。

两阶段验证

  1. 发现 Molecule:通过 issue_type = 'molecule'label = 'beads:template' 识别
  2. 验证子节点存在性:对每个 Molecule,检查其所有 parent-child 依赖的子 Issue 是否存在
for _, mol := range molecules {
    var orphanCount int
    err := db.QueryRow(`
        SELECT COUNT(*)
        FROM dependencies d
        WHERE d.depends_on_id = ?
          AND d.type = 'parent-child'
          AND NOT EXISTS (SELECT 1 FROM issues WHERE id = d.issue_id)
    `, mol.ID).Scan(&orphanCount)
    ...
}

性能考量:这里使用逐 Molecule 查询而非单一大查询,原因是:

  • ✅ 简化逻辑(每个 Molecule 独立计数)
  • ✅ 便于定位具体哪个 Molecule 有问题
  • ❌ N+1 查询问题(100 个 Molecule = 101 次查询)

这是一个可读性优先于性能的选择。深度验证是低频操作(用户手动触发),且 Molecule 数量通常有限(<100),因此 N+1 问题可接受。

moleculeInfoagentBeadInfo 结构

私有辅助结构:仅用于内部数据传递,不导出。

type moleculeInfo struct {
    ID         string
    Title      string
    ChildCount int  // 注意:实际代码中未使用此字段
}

type agentBeadInfo struct {
    ID         string
    Title      string
    RoleBead   string
    AgentState string
    RoleType   string
}

设计观察moleculeInfo.ChildCount 字段在定义中存在,但在实际扫描逻辑中未使用(查询仅返回 idtitle)。这是一个遗留字段,可能是早期设计迭代留下的。建议在未来重构中移除,避免误导维护者。

依赖关系分析

上游依赖(被谁调用)

深度验证模块是 诊断核心 的子模块,通过 RunDeepValidation 函数被 bd doctor 命令调用:

bd doctor 命令
    └── 诊断核心 (cmd.bd.doctor.types)
        └── 深度验证 (cmd.bd.doctor.deep) ← 本模块

调用者期望:

  1. 非阻塞:验证不应修改数据库(只读查询)
  2. 完整报告:即使部分检查失败,也应返回其他检查结果
  3. 可序列化:支持 JSON 输出供 MCP 集成消费

下游依赖(调用谁)

被调用模块 用途 耦合强度
配置文件 (internal/configfile) 检测后端类型(Dolt vs SQLite) 弱耦合(仅调用 LoadGetBackend
核心领域类型 (internal/types) 验证 AgentState 枚举值 弱耦合(仅调用 IsValid() 方法)
诊断核心 (DoctorCheck) 返回检查结果结构 强耦合(直接依赖 DoctorCheck 结构定义)
Dolt SQL 驱动 执行验证查询 中耦合(依赖标准 database/sql 接口,但查询针对 Dolt schema)

数据契约

输入

  • path string:Beads 仓库根目录路径(包含 .beads 子目录)

输出

  • DeepValidationResult:结构化诊断报告
  • JSON 字节流(通过 DeepValidationResultJSON

隐式契约

  1. 数据库 schema 必须符合预期(issues 表、dependencies 表、可选的 notes 列和 thread_id 列)
  2. AgentState 枚举必须定义 IsValid() 方法
  3. DoctorCheck 结构必须包含 StatusMessageDetailFix 字段

设计决策与权衡

1. 只读验证 vs 自动修复

选择:深度验证仅报告问题,不执行修复。

理由

  • 职责分离:验证是诊断,修复是治疗。混合两者会导致:
    • 难以测试(验证逻辑依赖修复副作用)
    • 用户失去控制权(可能不希望立即修复)
    • 错误传播复杂(修复失败如何影响验证结果?)
  • 可组合性:分离后,用户可以:
    • 先运行验证,审查报告
    • 再决定是否运行修复
    • 或编写自定义修复脚本

替代方案:某些系统(如 fsck)提供 -y 标志自动确认修复。Beads 选择通过 bd doctor --fix 命令显式触发修复,保持验证和修复的清晰边界。

2. 固定检查集合 vs 插件化检查

选择:六个检查函数硬编码在 RunDeepValidation 中,而非通过插件系统注册。

理由

  • 简单性优先:检查数量固定且有限(6 个),插件系统会增加复杂度
  • 编译时保证:硬编码确保所有检查都被执行,无遗漏风险
  • 性能可预测:无动态加载开销

扩展点:未来如需添加新检查,应:

  1. 添加新的 checkXxx 函数
  2. DeepValidationResult 中添加对应字段
  3. RunDeepValidation 中调用并聚合

这是一个显式优于隐式的设计。

3. SQL 查询 vs 应用层遍历

选择:所有检查通过 SQL 查询实现,而非在 Go 代码中遍历 Issue 图。

理由

  • 性能:数据库引擎优化了连接和存在性检查,应用层遍历需要加载全部数据到内存
  • 原子性:单个 SQL 查询在事务快照中执行,避免并发修改导致的不一致
  • 简洁性:SQL 表达存在性检查更直观(NOT EXISTS vs 多层嵌套循环)

代价

  • 数据库锁定:长查询可能阻塞其他操作(但 Dolt 支持 MVCC,影响有限)
  • Schema 耦合:查询硬编码表名和列名,schema 变更需同步更新查询

4. LIMIT 保护 vs 完整报告

选择:所有查询使用 LIMIT(10 或 20 或 100),输出仅展示前 3-5 个示例。

理由

  • 用户体验:终端输出不应被数百行错误淹没
  • 性能保护:大规模数据损坏时,避免查询返回数万行
  • 修复策略:修复命令(如 bd repair-deps)应处理所有问题,而非仅报告的问题

风险:用户可能低估问题规模。缓解措施:

  • 在消息中报告总数("Found 123 broken dependencies")
  • 在详情中说明"Examples: ...",暗示还有更多

5. 错误等级划分(Error vs Warning vs OK)

策略

检查 典型状态 理由
ParentConsistency Error 父子关系破损影响核心功能
DependencyIntegrity Error 依赖引用破损影响图遍历
EpicCompleteness Warning 状态不一致,但不影响功能
AgentBeadIntegrity Error Agent 元数据破损可能导致运行时错误
MailThreadIntegrity Warning 邮件线程引用可选,不影响核心功能
MoleculeIntegrity Error Molecule 结构破损影响工作流执行

设计洞察:错误等级反映对系统功能的影响程度,而非"数据损坏的严重性"。这是一个用户中心的设计:帮助用户优先处理最关键的问题。

使用指南

基本用法

# 运行深度验证(只读,不修改数据)
bd doctor --deep

# 查看 JSON 输出(供脚本消费)
bd doctor --deep --json | jq '.parent_consistency'

解读输出

Deep Validation Results
========================
Scanned: 1234 issues, 5678 dependencies

[✓] Parent Consistency: All parent-child relationships valid
[✗] Dependency Integrity: Found 3 broken dependencies
    Examples: ISSUE-123→ISSUE-456 (blocks), ISSUE-789→ISSUE-000 (attests)
    Fix: Run 'bd repair-deps' to remove broken dependencies
[!] Epic Completeness: Found 2 epics ready to close
    Examples: EPIC-1 (5/5), EPIC-2 (3/3)
    Fix: Run 'bd close <epic-id>' to close completed epics
...

Some checks failed. See details above.

符号含义

  • :OK(检查通过)
  • !:Warning(建议关注,但不影响功能)
  • :Error(需要修复)

与修复命令配合

# 1. 先运行验证,了解问题
bd doctor --deep

# 2. 根据建议运行修复
bd repair-deps          # 修复破损依赖
bd close EPIC-1         # 关闭已完成的 Epic

# 3. 再次验证,确认修复
bd doctor --deep

在脚本中使用

import subprocess
import json

result = subprocess.run(
    ["bd", "doctor", "--deep", "--json"],
    capture_output=True,
    text=True
)
report = json.loads(result.stdout)

if not report["overall_ok"]:
    for check in report["all_checks"]:
        if check["status"] == "error":
            print(f"Critical: {check['name']} - {check['message']}")
    exit(1)

边界情况与陷阱

1. SQLite 后端不支持

现象:运行深度验证时返回 Warning:"SQLite backend detected"。

原因:深度验证的 SQL 查询针对 Dolt schema 编写,SQLite 后端使用不同的表结构。

解决方案:运行 bd migrate --to-dolt 迁移到 Dolt 后端,或跳过深度验证。

2. 数据库不存在

现象:返回 OK,消息为 "N/A (no database)"。

原因.beads/dolt 目录不存在,可能是新初始化的仓库。

影响:无害,但用户可能误以为验证通过。注意区分 "N/A" 和 "All checks passed"。

3. JSON 函数不可用

现象:Agent Bead 检查返回 OK,消息为 "No agent beads to validate",但实际存在 Agent Issue。

原因:Dolt 版本过旧,不支持 JSON_EXTRACT 函数,查询回退失败。

解决方案:升级 Dolt,或手动检查 issues 表中 issue_type = 'agent' 的记录。

4. N+1 查询性能问题

现象:Molecule 数量多时(>1000),验证耗时显著增加。

原因checkMoleculeIntegrity 对每个 Molecule 执行独立查询。

缓解措施

  • 深度验证是低频操作,通常可接受
  • 如需优化,可重构为单一大查询(但会增加 SQL 复杂度)

5. 并发修改导致的不一致

现象:验证过程中,其他进程修改了数据库,导致结果不准确。

原因:Dolt 支持 MVCC,但深度验证未使用显式事务快照。

影响:罕见,因为验证是只读查询,且执行时间短。如需强一致性,应在验证前停止其他写入操作。

6. 遗留字段误导

注意moleculeInfo.ChildCount 字段未使用,是遗留代码。维护者不应依赖此字段。

与其他模块的关系

  • 诊断核心:深度验证是诊断系统的子模块,DoctorCheck 结构由诊断核心定义
  • 配置文件:用于检测后端类型,决定是否可以执行深度验证
  • 核心领域类型AgentState.IsValid() 方法用于验证 Agent 元数据
  • 存储接口:通过标准 database/sql 接口访问 Dolt,保持松耦合
  • MCP 集成DeepValidationResultJSON 输出可被 MCP 工具消费,供 AI 助手分析仓库健康状态

扩展指南

添加新的检查

  1. 定义检查函数
func checkXxxIntegrity(db *sql.DB) DoctorCheck {
    check := DoctorCheck{
        Name:     "Xxx Integrity",
        Category: CategoryMetadata,
    }
    // 执行 SQL 查询...
    // 设置 check.Status, check.Message, check.Detail, check.Fix
    return check
}
  1. 添加到 DeepValidationResult
type DeepValidationResult struct {
    // ... 现有字段 ...
    XxxIntegrity DoctorCheck `json:"xxx_integrity"`
}
  1. RunDeepValidation 中调用
result.XxxIntegrity = checkXxxIntegrity(db)
result.AllChecks = append(result.AllChecks, result.XxxIntegrity)
if result.XxxIntegrity.Status == StatusError {
    result.OverallOK = false
}
  1. 更新 PrintDeepValidationResult(可选,因为迭代 AllChecks 会自动包含)

修改现有检查

向后兼容:修改 SQL 查询或验证逻辑时,确保:

  • 不改变 DoctorCheck 的返回结构(字段名和类型)
  • 不改变错误等级(Error/Warning/OK),除非有充分理由
  • 在提交消息中说明变更原因

总结

深度验证模块是 Beads 系统的数据健康守护者。它通过一系列语义感知的 SQL 查询,系统性地发现 Issue 图中的结构性问题,为用户提供精确的诊断报告和修复建议。其设计核心是只读、非阻塞、可组合,确保验证过程本身不会引入新的问题,同时为后续修复提供可靠输入。

关键设计原则:

  1. 诊断与治疗分离:验证只报告,不修复
  2. 部分成功优于完全失败:单个检查失败不影响其他检查
  3. 用户体验优先:限制输出长度,提供修复建议
  4. Schema 探测与回退:优雅处理不同版本的数据库结构
  5. 显式优于隐式:硬编码检查集合,而非插件系统

理解这个模块的关键是认识到:引用完整性是应用层责任,而非数据库责任。深度验证填补了这一空白,确保 Beads 的 Issue 图始终保持语义一致。

On this page