C4 Plan
人类理解计划的结构和边界;AI在聊天中批准后执行。此技能不替代计划:它生成计划的视觉层和执行的简要摘要。
它也可以记录当前系统(kind: system):相同的图表和流程,没有状态、步骤或审批。请参见第5节。
聊天是真相的来源。 查看器仅显示计划:人类无法在那里编辑任何内容。问题和变更请求作为评论(或粘贴到聊天中)传来,你在聊天中回应,所有变更都通过YAML进行。
你从不编写HTML或手动构建URL。你编写一个YAML;脚本进行验证、生成链接和简要摘要。
计划 ─► arch.yaml ─► 编码 ─► 链接 ─► 人类查看并评论 ─► 你调整YAML ─► 在聊天中批准 ─► 简要摘要 ─► 执行
脚本:python3 <skill-dir>/scripts/arch_url.py(仅使用标准库 + PyYAML;jsonschema 可选)。
1. 从计划生成 arch.yaml
保存到计划旁边,命名为 <plan-name>.arch.yaml。模式:schema/arch.v1.json。完整示例:examples/pix.arch.yaml。
规则:
- 这是计划的架构,而非整个系统的架构。 包括计划创建、更改或删除的内容,以及理解所需的最小上下文(谁调用、谁被调用)。不要建模整个系统。
status:new/changed/removed/unchanged(默认)。上下文元素保持unchanged。- C4层次:根级为
person、system、external;container、database、queue在system内(或根级);component在container、database(表、迁移)或queue(事件)内;code仅在component内。 - 计划创建或更改的所有内容都会深入到底层代码。 每个
system、container、database、queue和component,若status为new/changed,则必须有children,向下深入直到code(validate会在缺失时发出警告)。未更改的内容保持封闭:那是上下文。 - 第4级(
code):计划创建或更改的文件、类、模块或函数,带有path。已存在且发生更改的文件为status: changed。列出更改的内容,而不是组件的全部代码(每个组件2到4个通常足够)。 - 关系连接最具体的元素(当存在时使用 code→code)。查看器会向上聚合到更高层级。
steps:每个计划步骤一个,顺序和标题相同。touches= 该步骤创建或更改的元素。flows:计划后系统如何工作(steps说明构建顺序;flows说明执行顺序)。1到3个流程:主路径和最重要的失败路径(例如:“客户通过PIX支付”、“QR码过期”)。每个hops[]为{from, to, label},并且必须遵循现有的关系,沿其方向或相反方向用于响应。使用最具体的元素(code),并将label写为发生的事件(“保存 txid 后再调用 PSP”),而不是关系名称。查看器会自动下降到每个跳转的级别。constraints:实现必须遵守的规则,例如可验证的规则(“基于 txid 的幂等性”、“增量迁移,无表锁定”),而不是描述。仅在有重要决策的地方放置:合约、与外部系统的边界、安全、数据、迁移、核心业务规则。没有约束的内容在执行时由你自行决定。- 如果仓库中存在合约,请在
relations[].contract中引用。
2. 验证并提供链接
python3 scripts/arch_url.py encode <plan>.arch.yaml
- 错误:修正YAML并重新运行。不通过验证不要提供链接。
- 警告:如果合理则修正(例如:新内容未深入到底层代码)。
- 向人类提供链接,一行,并附上计划更改内容的简短摘要(例如:“3个新元素,2个已修改”)。告知他可以按 C(或评论),点击卡片并提问或请求更改,并且批准是在此聊天中进行的。
查看器:encode 生成已发布版本的链接,https://gustavorana25.github.io/c4-model-skill/(静态;计划位于 #hash 中,不会发送到服务器)。$C4PLAN_VIEWER_URL 可更改主机,--local 使用本地构建 viewer/dist/index.html(仅用于测试查看器本身的更改)。
2b. 如果你有嵌入式浏览器:监听页面
如果你拥有浏览器工具(Claude Code 的浏览器面板、Cursor 的浏览器、Chrome 中的 Claude),在那里打开链接而不是仅提供它,并在人类查看计划时监听页面。
聊天是真相的来源。 页面只是一个捷径:人类指向一个或多个卡片并评论,你在聊天中响应,绝不在页面中。你在页面中唯一更改的是计划,使用 load(),当对话改变结构时。
按原样打开 encode 生成的链接:它已经是 https://。(使用 --local 时,通过 http:// 提供 viewer/dist/,例如:python3 -m http.server;某些嵌入式浏览器会丢弃 file:// 链接的 #hash。)
页面暴露 window.c4plan(使用浏览器的JavaScript工具运行):
| 调用 | 作用 |
|---|---|
await c4plan.next(30000) | 等待最多30秒以获取下一个事件。返回事件或 null。最大值为40秒(工具在大约45秒处截断)。 |
await c4plan.state() | 当前状态:url、plan、focus(打开的级别)、selected(人类正在查看的内容)、idleMs(他不再操作页面的时长)、doc。 |
c4plan.load(urlOrHash) | 替换图表为新版本,无需重新加载页面。 |
c4plan.stop() | 通知页面你已停止监听。 |
next() 的事件:
{event:"comment", targets:[{id,name}], view, text}:人类对这些元素发表了评论(可以是零个、一个或多个;view是打开的级别)。在聊天中回复,以名称开头:“关于 API Pix 和 清算队列:…”。如果是变更请求,则修改YAML、运行encode、调用load(newLink)并在聊天中说明更改内容。然后继续监听。{event:"stop", reason:"idle"}:人类有10分钟未操作页面,监听自动结束。说出停止语句(步骤3)并退出循环。
循环:
- 开始前,在聊天中说一行:"我已在浏览器中打开图表,并在您操作时监听。按 C(或评论)、点击卡片并书写:我在此处回复。当一切就绪时,请在此告诉我批准。" 如果没有此警告,人类会操作页面,聊天中无任何内容出现,并且他不知道发生了什么。
- 重复
await c4plan.next(30000)并处理每个事件。null仅表示“尚无事件”:再次调用,无需在聊天中评论。监听持续时间取决于人类与页面的交互(每次点击、按键或滚动都会重置时钟);由页面决定结束时间,使用stop。 - 在
stop到达时停止。在stop时,在聊天中说:"我已停止监听图表,因为页面已闲置。请在聊天中评论何时需要,或要求我再次监听。" 如果你因其他原因需要提前停止,调用c4plan.stop()并说出相同内容。 - 如果在监听时人类在聊天中发送消息,则循环结束:回复该消息。然后读取
(await c4plan.state()).idleMs:如果小于10分钟,他仍在页面中,因此返回循环,无需再次警告。如果他批准,调用c4plan.stop()并继续第3节。 - 如果人类在聊天中询问关于“这个”或“这个元素”,读取
state().selected以了解他在说什么。 - 在没有你监听的情况下,评论按钮会复制类似
关于 "API Pix" (pix-api) 在图表中:…的文本供人类粘贴到聊天中。括号中的 id 是 YAML 中的 id。
3. 当人类在聊天中批准时
只有他能批准,且仅在聊天中(“已批准”、“可以继续”、“好的,执行”)。沉默、监听结束或无评论不等于批准。
- 在
<plan>.arch.yaml中标记approved: true并从文件生成简要摘要:python3 scripts/arch_url.py brief <plan>.arch.yaml -o <plan>.arch.md - 用几行总结自第一个链接以来对话中发生的变化(约束、结构、流程)。
- 在计划中添加对
<plan>.arch.md的引用,然后继续执行。
如果人类粘贴查看器的链接(例如,在普通浏览器中打开),它仅用于查看:有效的版本是你的 <plan>.arch.yaml。
4. 遵守简要摘要执行
<plan>.arch.md 在执行期间是必需的:
- 遵守结构(元素、关系、流程)和所有约束。如果实现要求更改结构或违反约束,停止并询问。
- 引用的合约(
contract)未经询问不得更改。 - 在约束之外,优先采用最简单的方式并遵循现有代码的模式。
- 人类在聊天中的要求优先于你的原始提议。
- 最后,将实现的内容与YAML进行比较并报告差异(未预料到的新组件、关系之外的依赖、已更改的合约)。
5. 记录当前系统(kind: system)
当请求是理解或记录已存在的内容时(“记录架构”、“这个系统如何工作”、入职),没有计划:你读取仓库并生成带有 kind: system 的相同YAML。完整示例:examples/loja.arch.yaml。
version: 1
kind: system
title: 在线商店
description: 关于系统功能的一两句话。
如何构建:
- 在编写之前先阅读。 入口点(路由、处理器、消费者、任务)、清单(
package.json、docker-compose、基础设施)、迁移和外部服务客户端指示了容器、数据库、队列和外部服务。不要发明代码中未显示的组件;如果某些内容不确定,在聊天中说明。 - 没有
status、steps和approved。 所有内容都是系统的当前状态(validate会在任何残留时发出警告)。 - 流程是最重要的。 2到4个:对业务最重要的路径、主要的后台任务和最常见的失败案例。通过它们,新来人可以理解系统。
- 深度: 仅在流程穿越的地方深入到底层
code,带有真实的path(确认文件存在)。其余部分保持为container或component,封闭。 constraints变成团队规则,需要修改的人必须知道(幂等性、谁可以写入哪个表、不可更改的合约)。- 关系和流程遵循与计划相同的规则(第1节)。
交付:像计划一样使用 encode 生成链接。用一行说明系统包含的内容(“5个容器、2个外部系统、2个流程”),并说明可以在“流程”选项卡中跟踪流程并用 C 提问。如果有浏览器,监听页面(第2b节):评论是问题,你在聊天中回答,或是对文档的修正,你将其应用于YAML并用 load() 重新加载。
对于仓库中可版本化的文本,brief 生成Markdown文档(元素、关系和流程):
python3 scripts/arch_url.py brief docs/architecture.arch.yaml -o docs/architecture.md
稍后,关于该系统的计划可以基于此YAML:复制,将 kind 改为 plan 并用 status 标记更改的内容。