mcpField
G
generate-diffmap

generate-diffmap

github.com/tanishqkancharla开发22253 次安装2 天前更新
代码仓库

关于 generate-diffmap

generate-diffmap 是用于编写和分享软件变更说明的 Agent 技能,以持续更新的 Markdown 规格文档呈现现状、计划和进展。它指导作者先审查代码并确认范围,再用分阶段说明、图表和源码引用解释变更。

主要功能

  1. 01持续更新的 Markdown 规格文档
  2. 02起草前确认变更范围
  3. 03分阶段说明变更
  4. 04图表与调用栈视图
  5. 05链接源码的引用
  6. 06通过 Diffmap 提供和分享文档

适用场景

  1. 01记录现有拉取请求
  2. 02解释计划中的代码变更
  3. 03跟踪已完成的实现阶段

安装

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

$npx skills add https://github.com/tanishqkancharla/diffmap --skill generate-diffmap

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

附带文件agents/openai.yaml

详细介绍

持续维护的规格说明

规格说明是一个 Markdown 文件,路径为 specs/<short-kebab-case-name>.md,用于展示当前系统、计划和已完成的工作。随着计划变化和工作推进,持续更新它。若要演示现有拉取请求,请使用其规格说明(如果有);否则写在 .diffmap/ 下。写入前,请检查仓库中的路径和符号。

先确定范围。 写入前先阅读相关代码。如果设计、范围或阶段划分不明确,请先与用户确认,再开始大量编写:提供几个选项,并说明你推荐哪一个。

提供和分享

在仓库根目录运行:

npx @tanishqkancharla/diffmap list                   # reuse the URL if this file is already served
npx @tanishqkancharla/diffmap serve specs/<name>.md
npx @tanishqkancharla/diffmap share specs/<name>.md  # only when asked; prints https://diffmap.dev/g/<id>

保持服务持续运行,并将文件路径和 URL 告知用户。仅在用户提出要求时才打开浏览器。分享前,请提交已完成的工作,并让其中的引用指向该提交,如阶段完成时所示:share 会将每个被引用提交的差异保存到 gist 中,但没有提交的引用只会打开分享时文件的状态。分享的 gist 不会公开列出:任何拥有 URL 的人都可以阅读,包括它快照中的所有文件。拉取请求中的规格说明也可通过 https://diffmap.dev/<owner>/<repo>/pull/<n>/specs/<name>.md 访问,并固定到某个提交。

结构

面向需要快速了解变更的人来写。先从使用者会遇到的变化讲起,例如屏幕、命令、API 调用或错误,再根据读者的需要,逐步说明实现。规格说明通常包含问题概述、解决方案概述、目标与非目标、阶段和 参考资料;根据内容决定每部分需要写什么。

阶段。 每个阶段都要足够小,能够单独提交。规划中的阶段标题使用普通格式,进行中的标题加上 ⏳,已完成的标题加上 ✅。每个阶段都先从客户端视角简要说明 当前情况 和 提议方案,再按变更的特点展开说明:新流程可能需要图示和调用栈,重构可能需要调用栈差异,依赖项升级可能只需一两句话。篇幅应与变更相称,每件事只在适当的位置说明一次。规格说明用于解释变更,而不是跟踪任务。

图示。 图表、调用栈和代码往往比段落更能说明变更,因此, prose 冗长时不妨使用它们。只有在图示能展示读者需要了解的内容时才添加,不要为了填充版面而添加。

这些视图都符合一个模型:服务接收消息、更新自身状态,然后转发消息。每种视图都展示服务之间或单个服务内部的情况,既可以涵盖所有路径,也可以跟踪一条消息:

所有路径单条消息
服务之间mermaid 流程图:有哪些服务,各自负责什么services:消息如何穿过服务,以及它会改变哪些状态
单个服务内部伪代码和类型:服务的状态、载荷和逻辑callstack:服务如何将一条消息转化为结果

当各部分会保持状态、并行运行或分流时,使用 services;当它们是会返回、分支或提前返回的函数调用时,使用调用栈。Mermaid 时序图和状态图是更轻量的选项。如果一个视图需要展示超过约 7 个服务,请将其中一些合并,并另行说明。

  • 要展示变更,请在 mermaid 或 services 后添加 diff,并像调用栈那样让每行以 -(仅当前情况)、+(仅提议方案)或空格(两者共有)开头。
  • Mermaid 图表应在语言标记后使用 [标题] 添加标题,例如 mermaid diff [无效记录会在存储前停止]。services 代码围栏应在第一步之前使用 start "caption" 作为整个图表的标题,并在其下方用 > 行以几句话概述整个流程;每一步都要标注发生的情况。
  • 使用实际名称标注节点和箭头,并通过 %% ref 指令链接现有源代码。

调用栈。 将每行写成数据流形式:result = function(inputs);在重要位置使用 return 行。用 - 标记原有内容,用 + 标记变更,用空格标记未变更内容;差异应对比同一函数变更前后的情况。使用 ├── 和 └── 展示调用嵌套。通过源代码引用链接实际函数;未链接的辅助函数是伪代码,并非承诺提供的 API。调用栈控制在约 12 行,并将深入流程拆分为概览和每个变更后被调用函数各自的调用栈。

代码。 代码围栏应简短,并紧扣段落所述内容;用 // ... 省略未变更的代码。在语言标记后使用 {2-3} 高亮代码行(在 callstack 后使用 {3-4} 高亮行),并在底部用注释说明,而不要写冗长注释:对名称,无论其出现在哪里,都使用 // [!note symbol] text;对从代码围栏顶部开始计数的行,使用 // [!note L3-L5] text。调用栈也使用相同的说明方式,但注释符号为 #。

链接。 使用 references 链接现有源代码;计划中的符号写作普通文本。

行文

所有正文、注释和图示标签都遵循奥威尔在《政治与英语》中的六条规则。代码名称不属于术语。

示例阶段

此示例使用的是说明性文件和提交 SHA,而非 Diffmap 源码路径。此更改涉及几个层次,因此使用了多个视图;较小的阶段需要的视图更少。

### ⏳ Phase 1: Validate request input

**Today**

The handler passes records straight to the service. A client that sends an empty name gets a success response, and the bad record surfaces later as a storage error the client never sees, so they keep sending bad input.

**Proposed**

A client that sends an empty name gets an error naming the `name` field, so they can fix the request right away. Bulk import in Phase 2 needs every saved record to be valid, so this check comes first.

From the client's side, the same empty-name request now fails at once:

```ts
const response = await client.saveRecord({ name: "" });
// before: { ok: true }
// after:  { ok: false, error: "name must not be empty" }
```

Today every record reaches storage. In the proposed flow, a valid record follows the same save path, but an invalid one returns an error before storage. The unlinked `validateInput` helper is pseudocode, not a proposed public API:

```mermaid diff [Invalid records stop before storage]
 flowchart LR
-    A[requestHandler] -->|record| B[existingService]
+    A[requestHandler] -->|record| V[validateInput]
+    V -->|valid record| B[existingService]
+    V -->|invalid record| E[Return name error]
     B -->|record| D[Storage]
     %% ref node:A [[src/request.ts#requestHandler]]
     %% ref node:B [[src/service.ts#existingService]]
```

The call stack shows how the validation result controls the return path:

```callstack
 response = requestHandler(record) [[src/request.ts#requestHandler]]
-└── return existingService(record) [[src/service.ts#existingService]]
+├── error = validateInput(record) # reject empty names
+├── if error: return error
+├── result = existingService(record) [[src/service.ts#existingService]]
+│   ├── storage.save(record)
+│   └── return { ok: true }
+└── return result
```

In code, the handler returns before the existing save:

```ts {2-3}
function requestHandler(record: RecordInput) {
  const error = validateInput(record);
  if (error) return error;
  return existingService(record);
}
// [!note validateInput] Returns an error when `name` is blank, otherwise undefined.
// [!note L3] Storage never sees an invalid record.
```

The new check:

```ts
function validateInput(record: RecordInput) {
  if (record.name.trim() === "")
    return { ok: false, error: "name must not be empty" };
  return undefined;
}
```

阶段完成时

开始下一阶段之前:

  1. 提交代码。如果该阶段包含多次提交,则在以下步骤提到 SHA 的地方使用 <base>..<head>。
  2. 在 Today 和 Proposed 之后立即添加一个带有该 SHA 的 changes 代码围栏。它会呈现阶段摘要卡片。在 SHA 下方,按审阅顺序逐行列出审阅者应查看的文件路径:通常先列出面向客户端的入口点,再依次列出各层文件。省略无需仔细审阅的文件,例如锁文件、生成的代码、快照、测试样例和机械式重命名;摘要卡片会将它们折叠到“另外 N 个文件”下。
  3. 将阶段中更改的所有引用指向该提交:堆栈行、%% ref 指令和正文文本。
  4. 更新图表、调用栈和伪代码,使其与实现一致,并将标题标记为 ✅。
  5. 单独提交规范更新;其中需注明代码提交的 SHA。
  6. 重启 serve;它会在启动时检查提交引用。

示例阶段随后如下所示:

```changes
a1b2c3d
src/request.ts
src/validate.ts
```

```callstack
 response = requestHandler(record) [[a1b2c3d:src/request.ts#L8-L20]]
-└── return existingService(record) [[src/service.ts#existingService]]
+├── error = validateInput(record) [[a1b2c3d:src/validate.ts#L1-L9]]
+├── if error: return error
+├── result = existingService(record) [[src/service.ts#existingService]]
+│   ├── storage.save(record)
+│   └── return { ok: true }
+└── return result
```

源码引用

路径相对于仓库根目录。

  • [[path/to/file.ts#symbolName]] 会链接到 TypeScript 或 JavaScript 声明;如果名称有歧义,请限定名称,例如 [[src/store.ts#Store.save]]。
  • [[path]] 会链接到文件;[[path#L12-L30]] 会链接到一个行范围。
  • [[<sha>:path#L12-L30]] 会链接到提交中的行;如果阶段包含多次提交,则使用 <base>..<head>,其中 <base> 是首次提交之前的提交。行号按提交后的文件编号,因此无法链接已删除的行。可使用 git show <sha> -- <path> 和 git show <sha>:<path> | nl -ba 查找行号。
  • 不带提交的引用会打开该文件未提交的更改;如果没有未提交的更改,则打开当前文件。共享的 gist 会打开分享时的文件版本。
  • 在正文中,引用会呈现为可点击的行内代码;如需显示语法,请将其用反引号括起来。
  • 在 Mermaid 中,%% ref node:<id> [[reference]] 用于链接节点或参与者,%% ref edge:<index> [[reference]] 用于链接边或消息,索引按声明顺序从零开始。每个目标使用一条指令;如有需要,可使用多个引用。

代码围栏:mermaid 用于绘制图表;services 用于绘制服务、其状态以及服务间事件的动画图表(在任一围栏后添加 diff 可用 - 或 + 标记行);callstack 用于堆栈行;changes 用于提交或范围摘要(未提交更改时留空),并在其下方列出待审阅的文件;html 用于你编写的可信 HTML。其他语言用于伪代码和类型,可选用 {…} 高亮内容,并添加 [!note …] 行。在语言标记后添加 [Title],例如 ```callstack [Request flow],可为调用栈、代码围栏或 Mermaid 图表添加标题。

查阅其余内容

评论

支持 Markdown