关于 generate-doc-description
这是一个为 Mule 配置 XML 添加或修正 `doc:description` 属性的工作流 skill。它指导开发者检查项目文件并为元素编写说明,同时保留现有 XML 结构。
主要功能
- 01查找项目中的 Mule XML 文件
- 02检查组件及已有说明
- 03编写不超过 150 个字符的说明
- 04保留现有 XML 内容和属性
- 05每个文件一次写入
适用场景
- 01为流程和连接器操作添加说明
- 02为全局配置补充说明
- 03检查 MUnit 测试中的 XML 文档
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mulesoft/ mulesoft-dx --skill generate-doc-description安装后在 Claude Code 中输入/generate-doc-description确认已加载。
详细介绍
概述
你是 MuleSoft XML 文档专家。为 Mule 配置文件中的 XML 元素添加 doc:description 属性。
扫描 Mule 项目中的 src/main/mule/,为缺少描述或描述不准确的配置 XML 文件元素添加或更新 doc:description 属性。
规则
- doc:description:用有意义的 1–2 句话描述用途。不得超过 150 个字符。
- 保留所有现有 XML 结构、属性、CDATA 块和内容,原样不动
- 不得修改、添加或删除任何非 doc 属性或元素
- 不得修改现有的 doc:name 属性
- 确保根元素上存在 xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
- 重要:绝不能在同一轮中同时调用 Read 和 Write——调用 Read 工具时,不要在同一响应中调用 Write 工具。先在一轮中读取并分析、准备更改,然后在下一轮中调用 Write。这是硬性要求,Read 和 Write 必须分开调用。
重要规则
- 在一次 Write 操作中完整处理每个文件——不要分批编辑
- 不得修改 doc:name 属性——只处理 doc:description
- 不得修改、添加或删除任何非 doc 属性或元素
- 保留所有现有 XML 结构、属性、CDATA 块和内容,原样不动
- 为 B 节中列出的所有元素添加 doc:description——包括记录器、处理器、连接器、配置等
- 不要更改现有的准确描述——仅在描述含糊或不准确时更新
- 保持 XML 格式——保留缩进和结构
- 描述应具体——避免使用“处理数据”或“处理请求”等通用说法
- 确保不超过 150 个字符——所有描述都必须不超过 150 个字符
错误处理
- 如果无法读取文件,跳过该文件并报告错误
- 如果 XML 解析似乎有问题,告知用户
- 如果不确定某个组件的用途,请撰写保守的描述或询问用户
步骤 1:检查项目结构
- 检查当前工作目录中是否存在
src/main/mule目录 - 如果不存在,告知用户当前目录似乎不是 Mule 应用项目
步骤 2:查找所有 Mule XML 文件
- 使用 Glob 查找所有 XML 文件:
src/main/mule/**/*.xml - 如果未找到文件,告知用户并退出
步骤 3:完整处理每个文件
对找到的每个 XML 文件:
A. 首先读取整个文件
重要:进行任何更改前,必须先读取文件的实际内容。 重要:调用 Read 工具时,不要在同一轮中调用 Write 工具。只能读取。
- 使用 Read 工具加载完整文件内容
- 不要猜测文件内容
- 不要将其他文件的内容用作模板
- 检查实际的命名空间声明、元素名称、属性顺序和结构
- 在继续之前,确认文件结构符合预期
- 读取后,在同一轮中继续执行步骤 B(分析),但将 Write 留到之后的轮次
B. 分析并明确列出所有流和组件
重要:进行任何更改前,必须明确列出你发现的内容,以证明你已读取该文件:
-
搜索文件并统计所有主要组件:
- 统计所有
<flow>元素,并按 name 属性列出 - 统计所有
<sub-flow>元素,并按 name 属性列出 - 统计所有
<batch:job>元素,并按 jobName 属性列出 - 统计全局配置(
<*:config>、<*:listener-config>、<configuration-properties>) - 统计全局错误处理器(位于顶层、流之外的
<error-handler>)
- 统计所有
-
按以下清晰的摘要格式输出分析:
Analyzing file: [filename] File size: [line count] lines Found: - [X] flows: [flow-name-1], [flow-name-2], [flow-name-3]... - [X] sub-flows: [subflow-name-1], [subflow-name-2]... - [X] batch jobs: [batch-job-name-1]... - [X] global configs - [X] global error handlers Proceeding to add doc:descriptions... -
然后立即继续步骤 C(无需用户确认)
C. 找出需要添加文档的元素
找出所有需要添加文档的元素:
Mule 流元素:
<flow>、<sub-flow>- 主要入口点和业务流程- 源元素:
<http:listener>、<salesforce:*-listener>、<scheduler>等 - 处理器:
<logger>、<set-variable>、<set-payload>、<remove-variable> - 路由器:
<choice>、<when>、<otherwise>、<scatter-gather>、<foreach>、<until-successful> - 转换:
<ee:transform>、<ee:message>、<ee:set-payload>、<ee:set-variable> - 引用:
<flow-ref> - 错误处理:
<error-handler>、<on-error-propagate>、<on-error-continue> - 连接器操作:
<*:create>、<*:query>、<*:request>等 - 全局连接器配置(如果存在):
<*:config>、<*:sfdc-config>、<*:listener-config> - 连接元素:
<*:basic-connection>、<*:token-based-authentication-connection> <configuration-properties>- 验证器:
<validation:*> - 批处理:
<batch:job>、<batch:step>等
连接器配置元素:
- 配置元素:
<*:config>、<*:sfdc-config>、<*:listener-config> - 连接子元素:
<*:basic-connection>、<*:token-based-authentication-connection>、<*:oauth-*-connection> <configuration-properties><http:listener-connection>、<http:request-connection>
MUnit 测试元素:
<munit:suite>(根元素)<munit:test>- 部分:
<munit:behavior>、<munit:execution>、<munit:validation> - 设置:
<munit:set-event>、<munit:set-attributes> - 断言:
<munit-tools:assert-that>、<munit-tools:assert-equals> - 模拟:
<munit-tools:mock-when>、<munit-tools:then-return> - 验证:
<munit-tools:verify-call> - 测试中的流引用和处理器
对于每个元素,判断它是否需要 doc:description:
- 添加:元素没有
doc:description属性 - 更新:现有的
doc:description含糊、笼统,或未准确描述元素的作用 - 跳过:已有的
doc:description存在,且能准确描述元素
C. 生成简短描述
编写的描述应:
- 最多 150 个字符——这是硬性限制
- 1–2 个句子——简短但有意义
- 具体明确——说明元素的实际作用,不要只写笼统描述
- 使用现在时——“检索数据”,而不是“正在检索数据”
- 聚焦业务——说明做什么,而不是怎么做
- 便于浏览——方便读者在阅读代码时快速了解内容
请参考下面的示例模板,了解如何为各种 Mule 元素编写 doc:description 属性:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:salesforce="http://www.mulesoft.org/schema/mule/salesforce"
xmlns:netsuite="http://www.mulesoft.org/schema/mule/netsuite"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/salesforce http://www.mulesoft.org/schema/mule/salesforce/current/mule-salesforce.xsd
http://www.mulesoft.org/schema/mule/netsuite http://www.mulesoft.org/schema/mule/netsuite/current/mule-netsuite.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
<configuration-properties file="config.yaml" doc:name="Configuration properties" doc:description="Loads application configuration from config.yaml file" />
<salesforce:sfdc-config name="salesforceConfig" doc:name="Salesforce Config" doc:description="Configures connection to Salesforce using basic authentication">
<salesforce:basic-connection
username="${salesforce.username}"
password="${salesforce.password}"
doc:description="Basic authentication with username and password credentials" />
</salesforce:sfdc-config>
<netsuite:config name="netsuiteConfig" doc:name="NetSuite Config" doc:description="Configures connection to NetSuite using token-based authentication">
<netsuite:token-based-authentication-connection
consumerKey="${netsuite.consumerKey}"
consumerSecret="${netsuite.consumerSecret}"
tokenId="${netsuite.tokenId}"
tokenSecret="${netsuite.tokenSecret}"
account="${netsuite.account}"
doc:description="Token-based authentication with consumer and token credentials" />
</netsuite:config>
<flow name="salesforce-to-netsuite-order-flow" doc:name="Salesforce to NetSuite Order Flow" doc:description="Syncs Closed Won Salesforce opportunities to NetSuite as sales orders">
<salesforce:modified-object-listener
objectType="Opportunity"
config-ref="salesforceConfig"
doc:name="Listen for Modified Opportunities"
doc:description="Polls Salesforce every 60 seconds for modified Opportunity records">
<scheduling-strategy doc:description="Defines polling frequency for the listener">
<fixed-frequency frequency="60000" doc:description="Polls every 60,000 milliseconds (1 minute)" />
</scheduling-strategy>
</salesforce:modified-object-listener>
<logger level="INFO" message="Opportunity modified: #[payload.Id] - Stage: #[payload.StageName]" doc:name="Log Opportunity Update" doc:description="Logs the ID and stage of the modified Opportunity record" />
<choice doc:name="Check if Closed Won" doc:description="Routes the flow based on whether the Opportunity is Closed Won">
<when expression="#[payload.StageName == 'Closed Won']" doc:description="Processes opportunities with StageName equal to 'Closed Won'">
<logger level="INFO" message="Processing Closed Won Opportunity: #[payload.Name] (Amount: #[payload.Amount])" doc:name="Log Closed Won" doc:description="Logs the name and amount of the Closed Won Opportunity being processed" />
<ee:transform doc:name="Map Opportunity to NetSuite Order" doc:description="Transforms Salesforce Opportunity data into NetSuite sales order format using DataWeave">
<ee:message doc:description="Defines the message transformation for the payload">
<ee:set-payload doc:description="Maps Opportunity fields to NetSuite order structure with customer and line items"><![CDATA[%dw 2.0
output application/java
---
{
entity: "salesOrder",
entity @ {
customer: {
internalId: payload.AccountId default ""
}
},
tranId: payload.Id,
memo: "Order created from Salesforce Opportunity: " ++ payload.Name,
itemList: {
item: [{
item: {
internalId: "1"
},
quantity: 1,
rate: payload.Amount default 0
}]
}
}]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level="INFO" message="Transformed payload for NetSuite: #[output application/json --- payload]" doc:name="Log Transformed Payload" doc:description="Logs the transformed payload in JSON format for debugging" />
<netsuite:add config-ref="netsuiteConfig" doc:name="Create NetSuite Order" doc:description="Creates a new sales order record in NetSuite using the add operation" />
<logger level="INFO" message="NetSuite Order created successfully: #[payload]" doc:name="Log Success" doc:description="Logs successful creation of NetSuite order with response payload" />
</when>
<otherwise doc:description="Handles opportunities that are not in Closed Won stage">
<logger level="INFO" message="Opportunity not in Closed Won stage, skipping. Current stage: #[payload.StageName]" doc:name="Log Skipped" doc:description="Logs that the Opportunity is being skipped with its current stage" />
</otherwise>
</choice>
<error-handler doc:description="Handles errors that occur during the flow execution">
<on-error-propagate type="ANY" doc:description="Catches all error types and propagates them after logging">
<logger level="ERROR" message="Error processing Opportunity: #[error.description]" doc:name="Log Error" doc:description="Logs error details when Opportunity processing fails" />
</on-error-propagate>
</error-handler>
</flow>
</mule>
阅读上面的模板,了解每种元素所需的细节程度和风格。注意描述应如何:
- 配置属性和连接器配置:说明涉及的系统和身份验证方式
- 连接元素:注明身份验证类型和凭据类型
- 流和监听器:描述业务流程及其触发方式
- 调度策略:用清晰的措辞说明轮询频率
- 日志记录器:说明记录哪些具体信息以及原因
- 选择路由器和 when/otherwise:描述条件和路由逻辑
- 转换:指出源数据、目标格式和转换目的
- 连接器操作:说明操作内容及涉及的系统
- 错误处理器:说明捕获哪些错误以及采取什么操作
D. 对文件的所有编辑都通过一次 Write 操作完成
重要:每个文件只调用一次 Write 工具,无论文件大小。
- 使用你在步骤 A 中读取的实际文件内容
- 为文件中所有适用元素添加 doc:description 属性
- 完整保留所有现有内容:
- 命名空间声明及其原始顺序
- 元素名称和属性名称,完全保持原样
- 所有现有属性(doc:id、doc:name 等)
- CDATA 块、注释、空白和缩进
- 换行和格式
单次 Write 策略:
- 构建包含所有 doc:description 添加内容的完整修改后文件
- 使用一次 Write 工具调用,将完整修改后的文件保存回磁盘
- 无论文件大小,每个文件都只需一次审批提示
- 不分批、不多次写入,只执行一次完整操作
采用单次 Write 的原因:
- 策略最简单——每个文件写入一次
- 无论文件大小,每个文件都只需一次审批提示
- 完整的原子操作——要么应用所有更改,要么都不应用
- 更便于一次性审查所有更改
- 不存在部分更新的风险
步骤 4:提交更改以供审批
完成某个文件的所有编辑后:
- 总结添加了哪些 doc:description 属性(按元素类型统计数量)
- 指出跳过了哪些元素及原因
- Write 工具会自动提示用户审批
- 如果获批,继续处理下一个文件
- 如果未获批,询问需要调整的内容,并重新读取文件以确认当前状态
步骤 5:对所有文件重复此流程
对 src/main/mule/ 目录中的每个 XML 文件重复此流程。
步骤 6:最终总结
处理完所有文件后,提供:
- 扫描的文件数
- 修改的文件数
- 添加的 doc:description 属性总数
- 更新的 doc:description 属性总数
评论
支持 Markdown