首页
/ 从决策上下文到 ADR:agent-skills 如何用 orders 服务的事件溯源抉择测试"记录决策"技能

从决策上下文到 ADR:agent-skills 如何用 orders 服务的事件溯源抉择测试"记录决策"技能

2026-09-04 10:29:13作者:蔡怀权

本文以 agent-skills 仓库中 decision-context.md 这份"决策上下文"文档为核心,完整还原 orders 服务在审计需求下面临的三种架构选项及其权衡,并结合 documentation-and-adrs 技能定义行为评测案例 说明:一份合格的决策上下文应包含哪些要素,以及它如何被转化为一份结构完整的架构决策记录(ADR)。读完本文,你能掌握 ADR 中 Context/Alternatives/Consequences 各节的内容来源,并了解该仓库 Tier 3 行为评测如何驱动 Agent 完成"从决策上下文到 ADR"的完整流程。

一、决策上下文原文:orders 服务的审计困境

decision-context.md 是一份为架构决策服务的上下文文档,全文围绕一个真实的工程困境展开。逐段拆解其信息构成:

1. 现状与诉求(Context 素材)

文档开篇交代了两类事实:

  • 现状:orders 服务当前存储"可变的订单行"(mutable order rows),并以尽力而为(best-effort)的方式发出 webhook;
  • 诉求:审计方(Auditors)需要完整的状态转换历史;客服(Support)必须能够在任意历史时点重建订单(reconstruct an order at a prior point in time)。

这两个诉求直指当前模型的缺陷:可变行只保留"最终态",而 best-effort webhook 无法保证事件不丢。"完整状态转换历史"与"时间点重建"正是事件溯源(Event Sourcing)要解决的两个经典能力——可追溯性(traceability)与可重放性(replay)。

2. 候选方案(Alternatives 素材)

文档明确列出三个被讨论过的选项:

  1. 保留现有模型,追加一张 append-only 审计表(Keep the current model and add an append-only audit table);
  2. 对 orders 采用事件溯源,并构建读模型投影(Adopt event sourcing for orders and build read projections);
  3. 用数据库变更数据捕获(CDC)作为审计历史(Use database change-data capture as the audit history)。

3. 权衡与约束(Consequences 素材)

文档随后给出了关键的权衡陈述:

  • 事件溯源的收益:提升可追溯性与重放能力(improves traceability and replay);
  • 事件溯源的成本:引入投影重建(projection rebuilds)、事件版本化(event versioning)、最终一致性(eventual consistency)与运维复杂度;
  • 团队能力:团队已有事件流(event-stream)经验,降低了选项 2 的执行风险;
  • 外部依赖约束:报表服务(reporting service)期望的是同步读(synchronous reads),这与事件溯源天然的事件ually 一致读模型形成张力;
  • 作用域边界:该决策仅适用于 orders 限界上下文(bounded context),不波及整个系统。

这份文档的价值在于:它不是结论,而是决策的原材料——现状、诉求、候选项、各方案的利弊、团队能力、外部约束、作用域,全部就位,只差最后的"拍板"。

二、决策上下文如何对接 ADR:documentation-and-adrs 技能

在该仓库中,decision-context.md 对应的技能是 skills/documentation-and-adrs/SKILL.md。该技能的核心主张是:"记录决策,而不只是代码"——最有价值的文档捕获的是 why:导致决策的上下文、约束与权衡。代码展示了"构建了什么",文档解释"为什么这样构建"以及"考虑过哪些备选"。

何时该写 ADR

技能文档列出的触发条件与 orders 场景高度吻合:

  • 在相互竞争的方案之间做选择(Choosing between competing approaches)——对应决策上下文中的三个候选项;
  • 设计数据模型或数据库 schema(Designing a data model or database schema)——对应 mutable rows 与 event stream 的存储模型之争;
  • 任何回退代价高昂的决策(Any decision that would be expensive to reverse)——切换订单存储模型显然属于此类。

现有约定优先(Match the existing convention first)

技能文档要求:在创建 ADR 之前,先检查仓库上下文里是否已有既定约定——现存 ADR、项目说明、ADR 相关配置或工具(如 .adr-dir 文件)。既定约定优先于模板默认值,需要对齐三个方面:

  • 位置与格式:如 docs/adr/*.mdDocumentation/Decisions/*.rst、MADR 布局或 adr-tools 配置;匹配现有目录、文件扩展名与标记语言(Markdown vs reStructuredText);
  • 编号与命名:沿用现有序列与文件命名模式(ADR-004-Title.rst0004-title.md……),不要从 001 重新开始,也不要引入第二套编号体系;
  • 小节标题:复用项目既有的标题集合,而不是强加模板的标题。

若证据相互冲突,应把冲突暴露出来,而不是静默引入另一套体系。只有在确认不存在任何约定时,才使用默认的 docs/decisions/ 加顺序编号方案。

默认 ADR 模板与订单决策的四节映射

在无既有约定时,技能文档给出的默认模板(存储于 docs/decisions/,顺序编号)包含 Status、Date、Context、Decision、Alternatives Considered、Consequences 各节。以 技能文档中的 PostgreSQL 示例 为参照,orders 决策上下文可以清晰地映射进各节:

ADR 小节 从决策上下文中提取的内容
Context 可变订单行 + best-effort webhook 现状;审计需要完整状态转换历史;客服需要时点重建能力
Decision 三个候选中拍板其一(上下文中尚未落定,这正是 ADR 要补上的部分)
Alternatives Considered 选项 1(audit table)、选项 2(event sourcing + projections)、选项 3(CDC),各自标注 Pros/Cons/Rejected 理由
Consequences 事件溯源带来的投影重建、事件版本化、最终一致性与运维复杂度;报表服务同步读诉求带来的适配工作;仅适用于 orders 限界上下文的作用域声明

值得强调的是技能文档对 Alternatives 的要求:每个被否决的方案都要写明 Rejected 理由,而不仅是罗列缺点。对应到订单场景:选 CDC(选项 3)意味着审计历史与数据库绑定、重放语义弱于原生事件流;选 audit table(选项 1)能低成本获得追加历史,但"时点重建"仍需靠额外快照或日志回放支撑,且审计表与业务写入是两套机制,容易出现漂移;选事件溯源(选项 2)则把三个成本项(投影重建、版本化、最终一致)转化为长期运维负担——这正是 决策上下文 最后一段权衡陈述的来源。

ADR 生命周期

技能文档规定 ADR 的状态流转为:

PROPOSED → ACCEPTED → (SUPERSEDED or DEPRECATED)

并明确两条纪律:不要删除旧 ADR(它们承载历史上下文);决策变化时,写一份新 ADR 引用并取代(supersede)旧 ADR。这与"代码里不删历史,用 git 保留"的精神一致——文档同样通过版本化而非删除来表达演进。

三、这份决策上下文在评测体系中的角色

decision-context.md 并非普通文档,而是 evals/fixtures/ 下的评测夹具。理解它的定位需要看 evals/README.md 描述的三层评测体系:

层级 检查内容 运行方式
1. 结构层 frontmatter、命名、必需章节、命令一致性 CI(validate-skills.jsvalidate-commands.js
2. 触发与路由 正向 prompt 排名 top-k、负向 prompt 不排名、描述不碰撞 CI(run-evals.js
3. 行为层 遵循技能的 Agent 满足 expectations[] 按需(run-evals.js --behavioral,消耗 tokens)

评测案例:从 prompt 到 expectations

evals/cases/documentation-and-adrs.json 中定义了该夹具对应的行为评测:

{
  "id": 1,
  "prompt": "Record the decision to adopt event sourcing for the orders service as an ADR.",
  "expected_output": "An ADR capturing context, decision, alternatives considered, and consequences",
  "files": ["documentation-and-adrs"],
  "expectations": [
    "The ADR states context, decision, alternatives, and consequences distinctly",
    "Trade-offs and rejected options are recorded, not just the winning choice",
    "The document is written in timeless language describing current state"
  ]
}

其中 files: ["documentation-and-adrs"] 声明评测所需夹具的路径,它相对于 evals/fixtures/ 目录——因此执行评测时,Agent 拿到的工作区里就包含这份 orders 决策上下文。三条 expectations 分别验证了 ADR 的四节区分度、"落选方案与被拒绝理由必须记录"的要求,以及"用无时间性语言描述当前状态"的写作规范——例如 ADR 中应写"orders 服务采用事件溯源",而不是"我们在 2026 年决定迁移"。

执行机制:夹具如何变成 Agent 的工作区

scripts/run-evals.js 的源码可以看到 Tier 3 评测的完整链路:

  1. 物化工作区materializeWorkspace() 为每个评测创建临时目录,通过 fs.cpSyncfiles[] 声明的夹具(本例即 documentation-and-adrs/decision-context.md)从 evals/fixtures/ 复制进工作区,Agent 拿到的是真实可操作的项目输入,而不是想象中的场景;
  2. 无头执行:评测通过 claude -p 无头模式运行,带 --verbose --output-format stream-json 捕获完整转录(含工具调用),并以 --permission-mode acceptEdits 加预批准工具列表运行,让 Agent 真正能写文件、跑命令,而不是"口头描述将要做的事"。--append-system-prompt 会注入对应 SKILL.md 全文,执行超时上限 15 分钟;
  3. 评分:完整的 stream-json 转录被作为"不可信数据"用 TRACE 标记包裹,经 stdin 管道传给评分器(避免 argv 超长),评分器按 expectations[] 逐条判定并返回 JSON 结果,写入 evals/results/(gitignored)。评分器只看 Agent 实际做了什么(工具调用、文件编辑、命令执行),而非其声称做了什么;
  4. 清理finally 块删除临时工作区,防止夹具数据残留在可读的临时目录中。

这套机制保证了决策上下文夹具不是摆设:Agent 必须在真实拿到 decision-context.md 的前提下,产出一份能被逐条验证的 ADR。

四、可复用的决策上下文写作清单

把 orders 案例与 documentation-and-adrs 技能 的要求合起来,可以提炼出一份"决策上下文"写作清单。在下一次架构评审前,检查你的上下文文档是否包含:

  1. 现状一句话:当前系统如何工作(mutable rows + best-effort webhooks),缺陷在哪(只有最终态、事件可能丢失);
  2. 干系人诉求:谁需要什么能力(审计要完整状态转换历史,客服要时点重建),诉求尽量具体到可验证;
  3. 穷举候选项:至少列出被认真讨论过的 2~3 个选项,而不是只写"我们选了 A";
  4. 逐选项权衡:每个候选的收益、成本、被拒绝理由都要写全——evals/cases/documentation-and-adrs.json 的第二条 expectation 明确要求"记录被否决的方案,而不只是胜出者";
  5. 约束与边界:团队能力(有事件流经验)、外部系统约束(报表服务期望同步读)、作用域(仅 orders 限界上下文)——这些约束决定了同一个技术在不同团队、不同上下文里是否成立;
  6. 既有约定检查:写 ADR 前先确认项目是否有既定 ADR 目录、编号与格式约定,有则完全对齐,无则用默认模板。

最后呼应技能文档的 Verification 清单:决策上下文与 ADR 落盘后,应确认"所有重大架构决策都有 ADR""README 覆盖快速上手、命令与架构概览""已知坑(gotchas)在关键处内联标注""没有遗留被注释掉的代码"。决策上下文的终点不是一份会议纪要,而是一份未来的人类工程师和 Agent 都能据此理解"为什么是这样"的 ADR。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384