mcpField
S
system-design

system-design

github.com/pinchen147开发3256 次安装2 周前更新
代码仓库

关于 system-design

system-design 是供编码 Agent 设计或演进软件系统使用的技能。它以工作负载、不变量、故障模式和运维约束为依据评估架构,并生成可供后续工作的设计产物。

主要功能

  1. 01仓库与绿地项目设计流程
  2. 02工作负载估算与约束分析
  3. 03数据模型与一致性定义
  4. 04候选架构比较
  5. 05基于证据的建议与设计产物

适用场景

  1. 01规划新的生产系统
  2. 02评估代码仓库中的架构变更
  3. 03明确数据所有权与一致性规则
  4. 04为后续编码 Agent 会话记录设计决策

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pinchen147/system-design-skill --skill system-design

安装后在 Claude Code 中输入/system-design确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

ARCHETYPES.md
AUDIT.md
EXAMPLES.md
HEURISTICS.md
HTML-REPORT.md
INTERVIEW.md
agents/
openai.yaml
archetypes/
authoritative-state.md
control-security.md
data-delivery.md
derived-serving.md
realtime-sync.md
traffic-work.md
assets/
report-template.html
scripts/
render_report.py

详细介绍

系统设计

架构取决于不变量、工作负载数据、故障模式和运行约束,而不是凭感觉。首先绘制最简单且可用于生产的候选方案,只添加那些经得起证据检验、且在关键维度上有所不同的备选方案,基于证据链推荐一个方案,并留下设计工件,以便另一个编码 Agent 会话能够继续推进。

无论是在代码仓库还是从零开始,流程都相同;遵循生产实践,自然会得出适用于面试的推理方式。

每项建议都必须引用一个边界数据、不变量、明确命名的故障模式,或 HEURISTICS.md 中的一条原则。

默认不加载示例。只有当初稿中的建议或接口仍然流于笼统时,才查阅 EXAMPLES.md 中对应的 BAD/GOOD 对比,然后用相关数据、不变量、所有权边界或故障行为替换笼统表述。

流程

0. 运行流程前,先评估需求规模

当决策难以撤销、数据是关键依据,或确实存在多种结构上截然不同的可行设计时,这套流程才值得投入。如果某方案未达到 HEURISTICS.md 中的反过度设计门槛,或者某项已记录的决策已经决定了答案,就指出是哪项门槛或决策排除了其他选择,并用一段话直接作答——无需产出工件。把虚假的选择并列呈现为选项卡,比不写文档更糟。

运行流程时,先绘制最简单且可用于生产的设计。只有当候选方案在满足边界条件和不变量后仍然可行,且在关键维度上有所不同,才添加该方案——例如,经测量得出的规模边界,或在正确性、故障隔离、成本或可运维性方面占主导地位的风险。对于被需求、门槛或明确命名的故障排除的选项,用一行记录驳回原因;不要将其绘制、评分或审查为同等候选方案。候选方案最多三个,不以凑足三个为目标。

1. 定位并继续

列出现有设计——docs/design/*/design.json,或者在 Git 仓库之外列出 ./*/design.json——并读取每个文件的 slug、title 和 status。如果其中一个设计涵盖了当前需求,就加载它,并在开展新的调研前应用用户反馈;如果有两个设计都可能适用,就列出两者并询问用户选择哪一个。

否则,生成一个 kebab-case 的 slug,命名系统或子系统,而不是复述请求内容(commerce-layer,而不是 add-a-commerce-layer),并选择以下模式之一:

  • 代码仓库模式:需求涉及当前代码库时使用。现有系统即为架构 0。
  • 从零开始模式:尚无实现时使用。

用一行说明模式、原因、是否续用了现有设计,以及目标目录。

2. 确立当前事实

在仓库模式下,首先将每个顶层目录归类为系统代码、正在积极开发的第一方 vendored 代码,或依赖项、示例和构建输出。只有前两类属于范围内。目录大小并不能证明其重要性——最大的目录树通常不是系统本身,而 git log --format=format: --name-only -200 | sed 's#/.*##' | sort | uniq -c | sort -rn 通常足以厘清大多数情况。用一行说明分类,包括与需求表述相矛盾之处。

仅限于范围内的路径,阅读架构文档、ADR、领域词汇、配置,以及近期历史中的关键路径;还要阅读该系统形态中承载状态和副作用的内容:对于联网服务,是架构、API 和队列;对于客户端、桌面或嵌入式代码库,是入口和生命周期、状态所有者、写入与刷新路径、持久化键命名空间、磁盘格式、实体身份键,以及进程或沙箱边界。遇到下文所述的流程和不变量都已明确时,就停止调查。如果代码和架构不同,以代码和架构为准——在 requirements.conflicts 下记录差异;如果这会改变不变量,应先询问,而不是悄悄选边。

已确定的 ADR 属于约束,但作为草案、已被取代、重复,或指向本仓库以外位置的 ADR,不属于可用证据,而非约束;列出无法读取的内容。这些 ADR 也是第 8 步审计的参照模型,因此要记录每一份 ADR 的状态:一项已接受但被悄然违反的决策,与一项已被取代且从未移除的决策,是不同的发现。指出已涵盖此主题的文档——如果其中已有文档确定了需求的部分内容,请说明其结论,并将本轮工作聚焦于尚未解决的部分。端到端追踪面向用户的流程,并使用 HTML-REPORT.md 中的类型盘点每个组件。

在两种模式下,都要定义:

  • 核心实体及绝不能被破坏的不变量;
  • 系统接口及其一致性/幂等性约定;
  • 关键端到端流程,包括失败和恢复流程;
  • 事实来源存储与派生视图。

仅在无法从仓库或提示词中查明时,才询问用户决策。

3. 明确需求边界

使用 INTERVIEW.md 仅补全尚未解决的需求边界。提出编号问题,最多分三轮,每轮不超过八个问题;每个问题都提供建议默认值。如果没有用户可供回答,则采用默认值,而不是提问。必须明确功能范围、排除范围、数值化非功能目标、工作负载形态、团队/成本约束,以及最重要的三项特性。为每项假设标注。

4. 运行并检验约束边界

计算决定该系统规模的数字。对于处理请求的系统,这些数字包括平均和峰值 QPS、存储增长、带宽、缓存占用、并发量,以及该领域的负载分布特征(突发、倾斜、扇出、热点键、对象大小)。如果设备上的约束是决定性的,就用该约束所适用的单位进行计算:每个会话的字节数和往返次数、相对于提供商配额的请求量及其成本、可能被 OS 终止的进程中的内存上限、设备端存储增长、冷启动预算,以及离线偏差窗口。如果资金跨越了某个边界,就计算该设计所保护事件的单位经济效益。任何不适用的标准指标都应记为 n/a,并用一行说明原因;绝不要为了填满一行而编造数字。展示推导过程,并用 shell 命令验证算术结果。

按照 INTERVIEW.md 执行物理规律/CAP 合理性检查。使用 ARCHETYPES.md 中的精简路由器,根据受保护的不变量进行选择,然后仅加载选中的方案包。默认不要加载所有方案包。根据每个选定原型的 形态 检验约束边界;如果原型有 数字锚点,也要一并检验。若某原型的 不适用条件 被触发,则说明它匹配错误——应将其排除并说明原因,而不是引入本系统不需要的机制。绘制候选方案前,先解决矛盾。

5. 确定数据和一致性模型

对于错误数据模型而言,正确的拓扑也称不上设计。绘制任何内容之前,先针对每个核心实体说明:它在内存中和持久化存储中的表示、身份方案、哪个组件拥有排序权威、各字段类别如何解决冲突、写入何时变为持久化,以及垃圾回收或压缩方案。使用 HEURISTICS.md 中的冲突解决规则;规则应根据可用的协调能力选择,而不是根据复杂程度选择。

在候选方案出现之前,先将这些内容写入 dataModel。对于每个结构化存储,还要生成直观的数据库模式:为每张表或每个集合命名,只列出能够解释设计的字段,标明主键、分区键、排序键和去重键,并说明重要索引、关系、事实来源状态和保留说明。使用易读的卡片,例如 Ticket — id, eventId, seat, price, status, userId;不要写可执行的 DDL。如果候选方案在其中任何一项上存在分歧,该分歧本身就是候选方案的一个维度——见第 6 步。

6. 绘制候选方案

完整绘制最简单且可投入生产的架构。只有在另一个方案通过约束和不变量的检验,且在关键的结构、数据模型、一致性、成本或可运维性方面有所不同时,才添加它。常见的有效替代方案会针对经测量的规模边界,或主要的正确性、故障隔离、成本或可运维性风险进行优化。每个被淘汰的选项都保留为一行拒绝理由,并注明淘汰它的要求、门槛或故障模式。不要为了填满选项卡而凭空编造一个同类方案;最多三个。

在仓库模式下,每个方案都是架构 0 的演进,迁移成本是首要考量。候选方案必须满足 HTML-REPORT.md 中的差异性规则。如果难点在于数据模型,而非组件图(例如协同编辑、共识、账本、索引),则围绕数据模型生成候选方案,并保持拓扑结构不变。

每种分布式机制都必须有数字、不变量或具名故障模式作为依据。每个候选方案都必须说明至少一个真实存在的弱点,并通过所选 ARCHETYPES.md 中每种所涉及架构类型的 Staff 门槛——这些问题是合理的架构图无法回答的。

通过用本设计自身的方式作答,才能通过门槛:说明由哪个组件负责、它遵守什么数值,或它接受什么行为。重复门槛的措辞不算作答;将其作为并未实现该机制的设计的证据,正是这条规则要防止的问题。如果某种架构类型的门槛因采用了不同结构而不适用,请说明用什么结构取代了它,以及现在由什么机制覆盖该门槛所防范的故障——义务必须履行或明确撤销,绝不能丢弃。如果候选方案偏离了传统基线,请指出该基线,并证明这种偏离仍能覆盖其故障模式。

为每个候选方案编写一个以流程为先的画布:设置 canvas.primaryFlow,为每个组件提供近似中心点的 position,将名称控制在足够简短的范围内,以便在常规形状中居中显示,并遵循 HTML-REPORT.md 中的布局规则。该文档还列出了渲染器会自动处理的内容。

7. 做出决定并深入分析

使用 HEURISTICS.md 对每个候选方案评分,优先考虑用户最看重的三项特征。通过一条由证据串联而成的论证推荐一个方案。评分可以不出现在这条论证中——评分只是候选方案对自身的评价。论证应以一个边界数值、一项不变量或一个具名故障模式为依据。

解决在正确性、成本或可运维性方面压力最大的两三个决策。每项深入分析都必须记录压力、决策、被否决的备选方案、故障模式和证据。说明重试、超时、幂等性、协调、故障转移、可观测性、推出计划、最先出问题的环节,以及哪项测量结果会推翻推荐。

只有满足以下条件,设计才算完整:

  • 每条关键流程都以具名的持久化或最终效果收尾;
  • 每项不变量都只有一个强制执行权威;
  • 每项依赖都有截止时间、重试负责人和有界积压;
  • 每个权威存储都有确认点、故障域、RPO 和 RTO;
  • 每个派生视图都注明重建来源和游标;
  • 每个候选方案都有具名的首个故障点;
  • 每项推荐都有可证伪的证据链;
  • 每项未解决的不确定性都记录为假设或测量项;
  • 所有产物都通过结构检查和渲染检查。

渲染前,请验证:

  • 每条关键流程都能到达持久化或最终效果;
  • 每个队列/日志都声明了投递语义和幂等性语义;
  • 每个存储都标明是事实来源还是派生数据;
  • 每条依赖边都注明截止时间、重试负责人,以及其后方可排队工作量的上限;
  • 明确说明负载相对于排空能力的情况,包括在容量最低时重试恰好会增加多少负载;
  • 每个权威存储都注明其故障域、恢复路径,以及该路径可接受的数据丢失量和停机时间;
  • 每个结构化存储都有直观的架构设计,其字段、键、索引和关系均支持所述访问模式和不变量;
  • 每项架构和线协议变更都注明兼容方向,以及读写端的部署顺序;
  • 设计能够承受自身客户端带来的压力:重复提交、重连风暴、冷缓存,以及变慢而非彻底失败的依赖;
  • 已考虑突发流量、倾斜、扇出、热点键和部分故障;
  • 在相关情况下,已考虑安全、隐私、滥用、保留和删除;
  • 没有将任何关键深入分析推迟到含糊不清的后续步骤;
  • 每项发现都引用证据并通过全部四项债务测试;每项 blocking 发现都通过 ID 指明其违反的不变量或目标;
  • debt.checked 列出所有已检查的类别;本次运行无法确认的检查项都已记录,而非被丢弃。
8. 审查架构债务

仅限仓库模式,且仅在此时进行:某项发现的影响范围是相对于本次运行所推荐的候选方案来衡量的,而该候选方案直到上一步才出现。绿地项目没有已实现的架构可供比较,因此完全跳过此步骤。

遵循 AUDIT.md。各阶段的顺序才是关键,而非仪式:先收集结构事实——图、边契约、ADR 状态、变更历史——再做出任何判断;一次只按一个类别生成候选发现,且不要让发现者看到上一轮的列表;让每个候选项都通过机械门槛;将幸存项交给红队审查,红队只能看到主张,绝不能看到其背后的论证。模型是不可靠的架构问题检测器,却是可靠的反驳者,因此在有人试图推翻某项发现之前,任何内容都不得进入报告。

如果存在子 Agent 原语,则每个类别运行一个发现者,每个视角运行一个验证者。如果不存在,则按相同阶段内联执行,在每个边界处重新陈述任务说明,并丢弃上一阶段的推理。边发现边判断的一次性流程是唯一行不通的方式。

将结果写入 design.json 的 debt 下,包括已检查的内容和无法确定的内容。发现可以为 risks 和 nextSteps 提供依据;绝不能据此生成候选方案,也绝不能将其变成 ADR。

9. 编写、渲染并验证

编写 design.json,并在其旁边重新生成 DESIGN.md,原样保留任何由用户编写的 ## Notes。验证所有 id 和流程引用。

然后渲染并打开报告。只有报告已写入磁盘并且已打开,本次运行才算完成——只有 design.json 和 DESIGN.md,却没有报告,并不算完成的运行。

<skill-dir> 是此文件所在的目录,无论它安装在何处;脚本会相对于自身解析模板,因此绝对路径始终有效:

python3 <skill-dir>/scripts/render_report.py \
  --design docs/design/<slug>/design.json \
  --out "$TMPDIR/system-design-<slug>.html"

脚本会在写入报告后自行打开报告,因此没有需要额外记住的步骤。仅在无人查看时——例如脚本化或无头运行——才传入 --no-open。

如果不知道技能目录,应当查找,而不是跳过此步骤:ls ~/.claude/skills/system-design/scripts/render_report.py ~/.agents/skills/system-design/scripts/render_report.py 2>/dev/null 涵盖两种独立安装方式,而插件安装位于 ~/.claude/plugins/cache/ 下。绝不要将 assets/report-template.html 读入上下文,也不要手动重建报告;请参阅 HTML-REPORT.md。报告只能包含自身的标题/日期信息,不得包含原型或测试框架外壳。

然后确认渲染结果正常。渲染后的页面必须显示设计自身的 title,而不是模板中的 System design report 占位文本——如果不一致,表示 JSON 未能解析。标题在运行时设置,因此静态文件的 <title> 标签中仍会包含占位文本;应检查嵌入的 application/json 块,或者确认 __DESIGN_JSON__ 已不复存在。使用浏览器工具时,加载每条架构路由并读取隐藏的 report-diagnostics 元素:data-component-overlaps、data-route-collisions、data-text-overflows、data-fit-overflows 和 data-label-occlusions 必须全部为 0。任何非零值都是 design.json 缺陷——缩短名称、移动位置,然后重新渲染。没有浏览器工具时,应说明报告已渲染但未检查,而不是声称看到了无法查看的交互。

通过修改 design.json 反复迭代,绝不要手动编辑渲染后的 HTML。

10. 记录决策

用户做出选择后,将 status: decided。在仓库模式下,建议在 docs/adr/ 下创建 ADR,记录已采纳的候选方案、已否决的候选方案、证据和后果。在 ADR 的 Context 中注明步骤 2 中负责的文档,将其取代的任何 ADR 标记为已被取代,并从仓库索引文档的位置链接到 DESIGN.md。后续运行必须阅读该 ADR,除非有新证据,否则不得重新讨论该决策。

评论

支持 Markdown