阅读材料: 应用部分 3. 项目宪法:首次规则公投

模块「应用部分 3. 项目宪法:首次规则公投」中第 1 / 5 节课
您正在未登录状态下查看课程。 请登录,以保存进度并参加测试。

实践部分 3. 项目宪法:首次规则公投

状态:建议。immutable_principlesmutable_rules 分离,并明确设置 ttlmax_scoperollback_condition —— 这是一种稳健的实践。具有确定性平局决胜规则(tie-breaker)的代理自动公投属于前沿方案:其具体形式取决于特定团队和模型。

对于教学通关,手动填写 constitution.md 并检查可变规则是否具备 ttlmax_scoperollback_condition 即已足够。自动公投和外部仲裁属于完整生产路径。

此处的「项目宪法」是指一个版本化的不变量集合、可变规则及修正案通过程序。该集合在执行危险操作前进行校验。

同一个词,两个不同的文件

在第一卷中,项目宪法分布在三个文件中:mission.md(我们为何做这件事)、tech-stack.md(我们用什么技术编写)、roadmap.md(按什么顺序做什么)。该契约描述的是产品。

在第二卷中,同一个词出现了第四个文件 —— constitution.md。它描述的不是产品,而是安全自动化的边界:哪些代理行为被禁止,哪些在限制条件下被允许,谁以及如何修改规则。这是上层补充,而非替代。第一卷的文件保留原位,constitution.md 添加在旁边,并在任何危险操作前被读取。

如果你需要一句话的区分:mission/tech-stack/roadmap 回答「我们在构建什么」,constitution.md 回答「即使代理非常想做,也不能对系统做什么」。

在教学最小化场景中,一个包含两条不可变禁令和一条可变规则的小型 constitution.md 即已足够。代理公投、外部仲裁和剧本自动检查仅在完整路径中需要。本章依赖第一卷第6部分mission.mdtech-stack.mdroadmap.md 的来源)和第18部分(SDD 流程安全概念的来源)。

阅读前

  • 第一卷的支撑:第6部分引入 mission.mdtech-stack.mdroadmap.md;第18部分解释 SDD 安全性。
  • 本地教学案例:node_not_ready,因为它能清晰展示允许的温和操作与危险操作禁令之间的区别。
  • capstone/ 的足迹:两个 immutable_principles,一个 mutable_rule,以及针对 high_memory_usage 的简短 governance_protocol
  • 首次通过的主要术语:immutable_principlesmutable_rules。第三层 governance_protocol 为参考性质,仅在团队引入投票规则时才需要。
  • 可推迟的内容:代理公投、外部仲裁和剧本自动检查。

单独设置生产层的原因很简单:node_not_readyautoscale_200pct 等场景不给你聊天讨论的时间。危险操作必须通过正式网关,或被阻止。该网关的安全性我们将在第18部分. SDD 安全中处理。与现有运行代码的交互关联见第13部分. 现有项目支持

本章路线图

本章较长,无需线性阅读。行进地图:

  1. 最小教学场景。 手动填写 constitution.md:两个不可变禁令,一条带六个字段的可变规则。这就是通关所需的全部内容。
  2. 核心思想。 解释为什么最小场景是这样的设计。
  3. 通过 Qwen Code 访谈。 加速填写 constitution.md 的一种方法。首次通过时可以跳过 —— 手动填写同样有效。
  4. 完整路径。 governance_protocolchange_logdecision_hash、公投。首次通过时无需阅读:当团队拥有自动网关时,这些内容才会变得必要。

如果你是首次阅读,在「核心思想」部分后停止,去做练习。等用最小片段完成 capstone/constitution.md 后,再回来阅读完整路径。

目标

到本节结束时,你将为自动修复设计一个可用的 constitution.md。不变量和可变规范将变得清晰,通过代理公投演进,并在修改谱系中完全可追溯。

这在实践中的意义。代理不再依据零散的提示行事。它将每个决策与正式的项目契约进行核对。这种契约有助于加速对重复事件的响应,但不会将速度变成自动绕过备份、审计、影响半径(blast radius)和安全回滚条件的权利。

最小教学场景

教学案例

对于 node_not_ready,需要在 triage 阶段允许代理的温和重启,但禁止对生产数据库、备份和审计进行危险操作。目标是获得一个可以在任何生产操作前用肉眼检查的小型 constitution.md

准备工作

  • book2/examples/templates/proposal.md —— 修正案表格。
  • 一份不能自动执行的危险操作清单。
  • 一个可成为可变规则的重复性未知模式。

首次通过时可以使用以下起始集:

dangerous_actions:
  - delete_namespace
  - restart_database
  - bypass_audit_trace
candidate_mutable_rule:
  incident_type: node_not_ready
  pipeline_phase: triage
  permitted_actions: ["soft_restart_agent"]
  max_scope: "single_node"

ttl: "30d"
  rollback_condition: "repeat_incidents_same_node>=2 or Safety veto"

如果你将本章适配到自己的项目,请替换操作名称,但不要移除 max_scopettlrollback_condition

步骤

  1. 将至少两条 immutable_principles 记录为禁令,而非建议。
  2. 添加一条带 incident_typepipeline_phasepermitted_actionsmax_scopettlrollback_conditionmutable_rule
  3. 描述 governance_protocol:角色、法定人数、Safety 否决权和平局决胜规则。
  4. 填写简短的 proposal.md:规则为何出现、谁投了票、何时激活以及如何回滚。
  5. 用这个问题检查文件:「即使能降低 MTTR,代理也无法执行什么操作?」*预期:答案应在 immutable_principles 中,而非聊天中。*
  6. 与 [examples/spec-ci/](examples/spec-ci/README.md) 中的可运行类比进行比较:理念相同 —— 操作前必须有可检查的网关。

控制事实

每条可变规则都有 ttlmax_scoperollback_condition。如果缺少任一字段,该规则不得进入宪法,仍作为提案草案。

可用 capstone/ 中的同一个可运行类比检查文件:

cd book2/examples/constitution
python3 scripts/check.py \
  --constitution specs/constitution.yaml \
  --proposal proposals/valid_proposal.md

获得 verdict: PASS。然后用 proposals/missing_evidence.mdproposals/conflict_with_immutable.md 重复 —— 获得 verdict: BLOCK 及原因。这就是危险操作前的教学网关。

迁移到 high_memory_usage

本章的本地案例是 node_not_ready,但计分案例是 high_memory_usage。迁移通过一条原则性表述完成,而非复制规则。

node_not_ready 借鉴什么high_memory_usage 写入 capstone/constitution.md 的内容
不可变原则「无连续两次 OK 不得关闭事件」不可变原则「无确认 RSS 连续两次低于 80% 不得关闭 high_memory_usage
可变规则 soft_restart_agentttl: 30dmax_scope: single_node可变规则 restart_podttl: 14dmax_scope: single_podrollback_condition: 5xx_increase OR memory_percent>=90% after 2 windows
扩大影响半径时的 Safety 否决试图将 restart_pod 扩展到命名空间时的 Safety 否决

如果这条表述无法形成,说明本地案例尚未产生可迁移的原则 —— 在转入 capstone/ 前请回到该案例。

如何进入 capstone/

将两个 immutable_principles、一个 mutable_rule 和简短的 governance_protocol 移入 capstone/constitution.md。如果你做了 proposal.md,在 capstone/README.md 中留下一行规则出现的原因。如果未运行代理公投,不要移入完整的公投内容。

最小片段:

immutable_principles:
  - "不保留 audit_trace 不得执行 auto-remediation。"
  - "无确认备份不得触碰 stateful workload。"
mutable_rules:
  - incident_type: high_memory_usage
    pipeline_phase: recovery
    permitted_actions: ["restart_pod"]
    max_scope: "single_pod"
    ttl: "14d"
    rollback_condition: "memory_percent>=90% after 2 windows or 5xx increases"
governance_protocol: "任何 max_scope 的扩展都需要单独的 proposal。"

可审查足迹

在教学包中,将 constitution.mdproposal.mdchange_log 记录一起保存。无出处的修正案不算作 production SDD 的一部分。

核心思想

constitution.md 的第一层是 immutable_principlesimmutable_principles(不可变原则)是指永远不能被自动关闭的规则。这包括安全级别的禁令和义务:

  • 无当前备份不得重启生产数据库;
  • 不得为释放空间而删除备份;
  • 无确认稳定不得将事件转入 resolved
  • 不得在关键安全命名空间中执行绕过(bypass)。

将这些规范表述为不变量,而非建议。正是它们在压力时刻限制代理,当降低 MTTR 的最短路径可能引发更大级联故障时。

第二层是 mutable_rules。这是具有精确作用半径的可变规范(与 immutable_principles 不同,此类规则可通过正式程序取消或重写)。为每条规则指定至少六个字段。它们的含义:

  • incident_type —— 规则适用的事件类别;
  • pipeline_phase —— 响应阶段(triagerecovery 等);
  • permitted_actions —— 允许的操作列表;
  • max_scope —— 影响半径限制(例如 single_node);
  • ttl(生存时间,time to live)—— 规则有效期,之后需复审或续期;
  • rollback_condition —— 规则自动回滚的条件。

缺少这些字段,修正案将过于宽泛,开始与不变量竞争。比较两个版本。

差:

- id: node_not_ready_soft_restart
  incident_type: "NodeNotReady"
  permitted_actions: ["soft_restart_agent"]

问题:无 ttl,无 max_scope,无 rollback_condition。规则无限期且无影响边界。半年后无人会复审它。

好:

- id: node_not_ready_soft_restart
  incident_type: "NodeNotReady"
  pipeline_phase: "triage"
  permitted_actions: ["soft_restart_agent"]
  max_scope: "single_node"
  ttl: "30d"
  rollback_condition: "repeat_incidents_same_node>=2 or Safety veto"

例如,允许在 triage 阶段对 incident:NodeNotReady 进行温和重启(soft restart),但禁止在 recovery 阶段对 incident:DBWriteLag 执行。相同操作在不同上下文中对数据和可用性的风险不同。

首次通过的停顿点

如果你首次阅读至此,你已拥有本章通关所需的一切:两个不可变禁令、一条带六个字段的可变规则、理解其与第一卷 mission/tech-stack/roadmap 的区别。接下来是完整路径 —— governance_protocolchange_logdecision_hash、公投。当你的团队拥有自动网关和三四个人类角色时,这些机制才变得必要。对于计分的 capstone/constitution.md,它们不是必需的。

如果你的项目中还没有任何自动操作,直接跳到「产出物与就绪标准」部分,完整路径可在第8章后阅读(届时角色将在文件仲裁中再次出现)。

完整路径:governance_protocol

让演化触发器可观测:同一 pattern_id 发生三次及以上重复不可预测事件将启动强制修正案公投。该阈值将单一异常与规则中的稳定空白区分开,防止每次嘈杂告警后都修改宪法。

固定聚合窗口,例如48小时。在候选修正案(即提交公投的 proposal.md)中包含:

  • 输入事件;
  • 当前 unknown 分类;
  • 假设风险;
  • 预期效果;
  • 取消条件。

为什么这里需要多个角色,而第一卷中审查只需一人。在第一卷第16部分中,一个审查者足够,因为审查对象是教学 AgentClinic 中的功能代码。错误代价是重做功能。在 production 场景中,审查对象不同:对实时服务的自动危险操作。错误代价是数据丢失、影响半径扩大、P0 被悄悄关闭。一个审查者无法应对不是因为不够聪明,而是因为人类难以同时兼顾不变量正确性、剧本适用性和 production 风险。因此审查被拆分到不同角色,每个角色有自己狭窄的问题。最小形式下,这仍可以是同一代理的三个模型依次读取同一文件 —— 但它们的问题各不相同。

governance_protocol 中描述投票程序。内容包括代理角色、投票权重、法定人数、召集时限和确定性平局解决。最小配置 —— 三个角色:

  • Verifier(验证器)查找不变量违反;
  • Implementor(实现者)评估剧本适用性;
  • Safety(安全)检查影响半径、隐私和回滚条件。

通过条件设为两票赞成,规则 2 approve + no Safety-veto,触发后15分钟内召集,平局决胜规则 safety-first。在此规则下,Safety 的临界风险总是导致否决。

第四角色协调员(Coordinator)在 governance_protocol 中不投票。它在下一层级 —— 文件仲裁(第8部分)中出现,负责维护 judgment.md 和轮次秩序。在宪法层面,协调员仅将投票结果记录到 change_log

将每次更新固定为不可变足迹,而非无出处的修改。记录包含:

  • versionparent_version —— 当前和上一版宪法;
  • reason —— 修正案原因;
  • votes —— 各角色投票结果;
  • decision_hash —— 决策的加密哈希,可供后续复算验证;
  • incident_context —— 触发事件;
  • activation_time —— 修正案生效时刻;
  • 仓库内差异(diff)链接。

此类日志将修改历史转化为证据链。如果日后出现「代理为何获得执行某操作的权限」的问题,答案将不在团队聊天中,而在可复现的决策谱系中。

示例与应用

constitution.md 的基本结构可以这样:

immutable_principles:
  - id: prod_db_no_restart_without_backup
    rule: "Production database restart is forbidden unless a verified backup exists."
    enforcement: "always_on"

  - id: backups_are_protected_assets
    rule: "Backup deletion, overwrite, or quarantine bypass cannot be executed automatically."
    enforcement: "always_on"

mutable_rules:
  - id: node_not_ready_soft_restart_triage
    incident_type: "NodeNotReady"
    pipeline_phase: "triage"
    permitted_actions:
      - "cordon_node"
      - "soft_restart_agent"
    max_scope: "single_node"
    ttl: "30d"

rollback_condition: "increase in repeat incidents or Safety veto"

governance_protocol:
  roles:
    verifier:
      vote_weight: 1
    implementor:
      vote_weight: 1
    safety:
      vote_weight: 1
      veto: "critical_risk"
  quorum: 2
  pass_rule: "at_least_2_approve_and_no_safety_veto"
  convene_after: "3_unknown_incidents_same_pattern"
  convene_within: "15m"
  tie_breaker: "safety_first_then_latest_matching_precedent"

change_log:
  - version: "1.2.0"
    parent_version: "1.1.0"
    reason: "3 unknown NodeNotReady incidents in 48h"
    votes:
      verifier: "approve"
      implementor: "approve"
      safety: "abstain"
    decision_hash: "sha256:..."
    activation_time: "2026-05-17T12:00:00Z"

将宪法连接到执行剧本前的网关检查,而非之后。步骤顺序:

  1. 本地脚本检查 immutable_principlesmutable_rules
  2. Qwen Code 在规划模式(Plan Mode)下解释风险和空白;
  3. 执行者获得操作权限。

命令 /constitution/tasks 不是 Qwen Code 的内置命令。如需使用,请将其设为项目自定义命令(project custom commands)。

通过 Qwen Code 访谈

在手动编写 constitution.md 之前,先进行与第一卷第6部分相同的访谈。生产层为经典三元组 mission/tech-stack/roadmap 增加了两个边界,进入这些边界不能没有人类的明确决策:代理有权在无确认情况下执行哪些操作、谁获得否决权、triage 阶段允许的最大影响半径是多少。

请求:

/clear
我们正在扩展 AgentClinic-production 的宪法。
查看 @specs/mission.md、@specs/tech-stack.md、@specs/roadmap.md
和 @specs/playbooks/node-not-ready.md。

创建 @specs/constitution.md 草案,包含三个部分:
- immutable_principles
- mutable_rules
- governance_protocol

在写入磁盘前,向我提出恰好三个分组问题:
1. 代理在 production 中哪些操作永远被禁止(备份、审计、密钥)。
2. 哪些操作可在 triage 阶段委托,附带影响半径限制和生存期(ttl)。
3. 谁投票、谁有否决权、公投按什么阈值召集。

暂时不要写文件。在我回答后展示修改计划,等待批准。

如果 Qwen Code 未经提问直接开始写 YAML,请制止它:

停下。访谈结束前不要写入文件。
先提出三个分组问题,如 QWEN.md 中所述。

人类对访谈的良好回答包含决策,而非愿望:

不可变原则:
禁止任何无验证备份的生产数据库自动重启。
禁止任何自动删除备份、审计和密钥的操作 —— 即使面临释放空间的压力。
事件无连续两次 OK 不得转入 resolved。

可变规则:
在 triage 阶段,NodeNotReady 允许 soft_restart_agent,max_scope=single_node,ttl=30d。
规则回滚条件 —— 同一节点重复两次事件或 Safety 否决。
禁止未经公投扩大 max_scope。

治理:
Verifier、Implementor、Safety 投票。每票权重为 1。
法定人数 —— 2 票赞成且无 Safety 否决。
48 小时内同一 pattern_id 发生三次 unknown 事件后召集公投。
平局决胜规则 —— safety_first。

然后让 Qwen 检查自己的草案:

检查 @specs/constitution.md。
找出表述为建议的不可变规则。

找出缺少 ttl、max_scope 或 rollback_condition 的可变规则。
找出缺少平局决胜规则(tie-breaker)的 governance_protocol。
不要修改文件,返回不符项列表。

此步骤的典型错误:

  • 不可变规则写成「尽量避免」—— 这是建议,不是禁令;
  • 可变规则缺少 rollback_condition,事件发生时规则变成无限期;
  • governance_protocol 未描述平局决胜规则 —— 平局时系统挂起;
  • change_log 缺失,宪法的首次变更即失去出处。

仅当通过此清单后,才将草案固定到项目中。在教学 book2/ 中,此步骤不需要 git 命令:重要的是可读的 constitution.md 及规则出处。

> 宪法网关:可运行类比与项目接口。 可运行检查位于 [examples/constitution/](examples/constitution/README.md) —— 它读取宪法 YAML 和带 YAML-frontmatter 的 Markdown(修正案提案),返回 verdict: PASS|BLOCK 和阻止项列表。计分时使用它即已足够。在实际项目中,此网关还补充两步:Qwen Code 规划模式查询,以及剧本 max_scope 对规则 max_scope 的检查。三个步骤作为一个整体执行。

# [runnable] —— 提案对宪法的检查
python3 book2/examples/constitution/scripts/check.py \
  --constitution book2/examples/constitution/specs/constitution.yaml \
  --proposal book2/examples/constitution/proposals/valid_proposal.md

# [project script] —— 在你的宪法和剧本上执行相同检查
python3 scripts/constitution/check.py \
  --constitution specs/constitution.yaml \
  --proposal proposals/<your-proposal>.md

# [project script] —— Qwen 规划模式,单独网关
qwen -p "检查 @specs/constitution.yaml 和 @specs/playbooks/node-not-ready.md。
模式:仅规划。说明修复计划是否违反 immutable_principles

以及需要哪些 mutable_rules 才能通过。" \
  --approval-mode plan \
  --output-format json \
  > out/node-not-ready-constitution-review.json
flowchart TD
A[事件] --> B[规划模式与脚本检查不可变性] --> C[可变规则检查] --> D[通过 / 阻止] --> E[执行的操作]
C --> F[未知事件] --> G[达到未知阈值] --> H[形成提案] --> I[公投] --> J[提交] --> K[新宪法]

公投适合用重放场景训练。三个相同的 unknown 事件创建 proposal.md,代理投票,通过的修正案以决策哈希进入 change_log

示例:临时规则 hotfix_ticketing_flood 可允许12小时内简化工单路由。条件是存在恢复点(checkpoint)并保留审计不可丢失的不变禁令。通过后检查修正案是否未变成无限期。确认 ttlrollback_conditiondecision_hashactivation_time 与变更记录一起可见于仓库。

总结

constitution.md 为自动修复设定了边界:代理可以自适应什么,以及无权为局部优化而关闭什么。

各层在此边界中的角色:

  • 不变量保护备份、审计、数据和关键区域;
  • 可变层允许针对重复事件细化剧本;
  • 代理公投使规则变更可检查;
  • 修改谱系保存原因、投票、决策哈希和激活时刻。

接下来,这些规范将在 LLM 对决中接受检验:验证器对阵实现者。

产出物与就绪标准

产出物就绪条件
specs/constitution.md不可变规则表述为禁令而非建议;从文件中能看出即使能改善 MTTR,代理也无法执行什么操作
一条 mutable_ruleincident_typepipeline_phasepermitted_actionsmax_scopettlrollback_condition 六个字段全部填写
proposal.md 或规则出处记录修正案有出现原因,否则不属于 SDD 包的一部分

完整路径添加若干不同影响半径的修正案、带 parent_version、投票和 decision_hashchange_log 记录,以及在执行剧本前检查宪法的项目网关。其就绪标准是:网关确实能在执行前阻止违反不可变层的行为,公投有法定人数、Safety 否决权和确定性平局决胜规则,通过的修正案可从事件上下文追溯到差异(diff)。

实践

  1. 打开 book2/examples/templates/proposal.md,为一个危险领域(部署、迁移、事件、密钥)填写:至少两条 immutable_principles(作为禁令)和一条带 incident_typepipeline_phasepermitted_actionsmax_scopettlrollback_conditionmutable_rule预期:每条可变规则包含全部六个字段;教学场景的控制事实得到满足。
  2. 记录 governance_protocol:角色、法定人数、Safety 否决权和平局决胜规则;提出问题「即使能降低 MTTR,代理也无法执行什么操作?」*预期:答案在 immutable_principles 中,而非聊天中。*
  1. 将两个 immutable_principles、一条 mutable_rule 和简短 governance_protocol 移入 capstone/constitution.md(格式见本章教学场景片段);如果运行过 proposal.md,在 capstone/README.md 中添加一行规则出现的原因。预期:无出处的修正案不进入 SDD 包。

自测题

  1. 项目规则中哪些应是不可变的,哪些不应是?
  2. 为什么可变规则需要 ttl,没有它一年后会发生什么?
  3. Safety 否决时应发生什么,为什么不能用两个 approve 绕过它?
  4. 48 小时内三次相同的 NodeNotReady 触发了公投,但此时正有活跃事件进行。你会接受、推迟还是回滚该修正案?
我的笔记
0 / 10000

笔记保存在当前浏览器中。在其他设备上将不会显示。

课程菜单

课程

Production SDD for Qwen Code CLI. Part 2
进度 0 / 100