diff --git a/internal/cli/schema_agent_metadata/doc.json b/internal/cli/schema_agent_metadata/doc.json index 5702d4f0..eaa8b202 100644 --- a/internal/cli/schema_agent_metadata/doc.json +++ b/internal/cli/schema_agent_metadata/doc.json @@ -4712,7 +4712,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], @@ -4729,14 +4729,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "candidates": [ { "value": "向文档插入块元素", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。" } ] }, @@ -4764,25 +4764,25 @@ }, "avoid_when": { "value": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "candidates": [ { "value": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。" } ] }, @@ -4822,7 +4822,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "candidates": [ { "value": [ @@ -4832,7 +4832,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。" } ] }, @@ -4905,7 +4905,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。" } ] }, @@ -4925,21 +4925,23 @@ }, "use_when": { "value": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "candidates": [ { "value": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。" } ] } @@ -4968,7 +4970,8 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.insert_document_block" ], "use_when": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ] }, "doc block list": { @@ -4992,14 +4995,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": "查询文档一级块元素列表", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -5033,7 +5036,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ @@ -5043,7 +5046,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -5083,7 +5086,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ @@ -5093,7 +5096,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -5172,7 +5175,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -5192,21 +5195,21 @@ }, "use_when": { "value": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。" } ] } @@ -5239,7 +5242,7 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.list_document_blocks" ], "use_when": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ] }, "doc block update": { @@ -6949,7 +6952,8 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "confirmation": "not_required", "effect": "write", @@ -6964,14 +6968,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": "更新指定文档评论的文字内容和可选 @用户/@群。", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。" } ] }, @@ -6993,21 +6997,23 @@ }, "avoid_when": { "value": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。" } ] }, @@ -7063,7 +7069,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ @@ -7073,7 +7079,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。" } ] }, @@ -7166,7 +7172,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。" } ] }, @@ -7194,21 +7200,21 @@ }, "use_when": { "value": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。" } ] } @@ -7229,7 +7235,7 @@ "structured-hint:internal/cli/schema_hints/products/doc.json" ], "use_when": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ] }, "doc copy": { @@ -7516,14 +7522,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7558,7 +7564,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ @@ -7569,7 +7575,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7609,7 +7615,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ @@ -7619,7 +7625,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7698,7 +7704,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7718,23 +7724,23 @@ }, "use_when": { "value": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] } @@ -7766,8 +7772,8 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.create_document" ], "use_when": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ] }, "doc delete": { diff --git a/internal/cli/schema_agent_metadata/drive.json b/internal/cli/schema_agent_metadata/drive.json index 233c3b9d..a3244f20 100644 --- a/internal/cli/schema_agent_metadata/drive.json +++ b/internal/cli/schema_agent_metadata/drive.json @@ -10481,6 +10481,7 @@ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], @@ -10497,14 +10498,14 @@ "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": "上传本地文件到钉盘或文档空间,或按节点 ID 确认覆盖已有文件", "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -10529,26 +10530,28 @@ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -10604,7 +10607,7 @@ "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ @@ -10614,7 +10617,7 @@ "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -10707,7 +10710,7 @@ "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。" } ] }, @@ -10737,25 +10740,25 @@ "value": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ], "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "candidates": [ { "value": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ], "source": "internal/cli/schema_hints/selection/drive.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。" } ] } @@ -10780,7 +10783,7 @@ "use_when": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ] }, diff --git a/internal/cli/schema_agent_metadata/index.json b/internal/cli/schema_agent_metadata/index.json index 9cc51b94..72b3b8e2 100644 --- a/internal/cli/schema_agent_metadata/index.json +++ b/internal/cli/schema_agent_metadata/index.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", + "source_hash": "sha256:f239237a9b87fa5a95a0520b2e2f2a112e117b273de8418763ba0ecd8652b317", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "coverage": { "surface_products": 26, @@ -12,8 +12,8 @@ "tools_with_avoid_when": 875, "tools_with_examples": 875, "tools_with_interface_mode": 875, - "unmatched_skill_tools": 96, - "unreviewed_skill_tools": 11 + "unmatched_skill_tools": 97, + "unreviewed_skill_tools": 12 }, "products": { "aisearch": { diff --git a/internal/cli/schema_agent_metadata_audit.json b/internal/cli/schema_agent_metadata_audit.json index 8526d83f..95089fe3 100644 --- a/internal/cli/schema_agent_metadata_audit.json +++ b/internal/cli/schema_agent_metadata_audit.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", + "source_hash": "sha256:f239237a9b87fa5a95a0520b2e2f2a112e117b273de8418763ba0ecd8652b317", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "source_files": 160, "hint_files": 54, @@ -36,8 +36,8 @@ "tools_with_avoid_when": 875, "tools_with_examples": 875, "tools_with_interface_mode": 875, - "unmatched_skill_tools": 96, - "unreviewed_skill_tools": 11 + "unmatched_skill_tools": 97, + "unreviewed_skill_tools": 12 }, "source_products": [ "agoal", @@ -1301,6 +1301,30 @@ "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" } }, + { + "tool_path": "doc drive upload", + "source": "skills/mono/references/products/doc.md", + "line": 668, + "candidates": [ + "doc upload", + "drive upload", + "doc +comment-create" + ] + }, + { + "tool_path": "doc import", + "source": "skills/mono/references/products/doc.md", + "line": 669, + "candidates": [ + "doc import get", + "doc +comment-create", + "doc +comment-list" + ], + "review": { + "status": "stale", + "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" + } + }, { "tool_path": "doc import", "source": "skills/mono/references/products/doc.md", @@ -1315,6 +1339,30 @@ "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" } }, + { + "tool_path": "doc drive upload", + "source": "skills/mono/references/products/doc.md", + "line": 745, + "candidates": [ + "doc upload", + "drive upload", + "doc +comment-create" + ] + }, + { + "tool_path": "doc import", + "source": "skills/mono/references/products/doc.md", + "line": 746, + "candidates": [ + "doc import get", + "doc +comment-create", + "doc +comment-list" + ], + "review": { + "status": "stale", + "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" + } + }, { "tool_path": "doc import", "source": "skills/mono/references/products/doc.md", @@ -1357,34 +1405,6 @@ "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" } }, - { - "tool_path": "doc import", - "source": "skills/mono/references/products/doc/doc-import.md", - "line": 12, - "candidates": [ - "doc import get", - "doc +comment-create", - "doc +comment-list" - ], - "review": { - "status": "stale", - "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" - } - }, - { - "tool_path": "doc import", - "source": "skills/mono/references/products/doc/doc-import.md", - "line": 13, - "candidates": [ - "doc import get", - "doc +comment-create", - "doc +comment-list" - ], - "review": { - "status": "stale", - "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" - } - }, { "tool_path": "doc import", "source": "skills/mono/references/products/doc/doc-import.md", @@ -1413,6 +1433,34 @@ "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" } }, + { + "tool_path": "doc import", + "source": "skills/mono/references/products/doc/doc-import.md", + "line": 16, + "candidates": [ + "doc import get", + "doc +comment-create", + "doc +comment-list" + ], + "review": { + "status": "stale", + "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" + } + }, + { + "tool_path": "doc import", + "source": "skills/mono/references/products/doc/doc-import.md", + "line": 17, + "candidates": [ + "doc import get", + "doc +comment-create", + "doc +comment-list" + ], + "review": { + "status": "stale", + "reason": "旧版 Skill 或说明性引用,当前公开命令面无等价 leaf,禁止词法模糊映射" + } + }, { "tool_path": "event consume user_im_message_receive_o2o_all", "source": "skills/mono/references/products/event.md", diff --git a/internal/cli/schema_catalog/catalog.json b/internal/cli/schema_catalog/catalog.json index c4df502f..453f8da8 100644 --- a/internal/cli/schema_catalog/catalog.json +++ b/internal/cli/schema_catalog/catalog.json @@ -1,18 +1,18 @@ { "version": 1, "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", - "source_hash": "sha256:3246b6b86cec02dd90b7cd093310667d926d62d3237d3408cfccc13ad3751b45", + "source_hash": "sha256:eddcc39cfdf906e0b47c896abc081fd2b5fc81150023f99938deb9def8b07d9e", "catalog": { "agent_metadata": { "products_with_metadata": 26, "source": "embedded-skill-metadata", - "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", + "source_hash": "sha256:f239237a9b87fa5a95a0520b2e2f2a112e117b273de8418763ba0ecd8652b317", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "surface_products": 26, "surface_tools": 875, "tools_with_agent_summary": 875, "tools_with_metadata": 875, - "unmatched_skill_tools": 96, + "unmatched_skill_tools": 97, "version": 1 }, "count": 26, @@ -15405,8 +15405,8 @@ "risk": "medium", "title": "创建文档", "use_when": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ] }, { @@ -15791,7 +15791,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], @@ -15815,7 +15815,8 @@ "risk": "medium", "title": "插入块元素", "use_when": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ] }, { @@ -15878,7 +15879,7 @@ "risk": "low", "title": "查询块元素", "use_when": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ] }, { @@ -16799,7 +16800,8 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "canonical_path": "doc.update_comment", "cli_name": "update", @@ -16817,7 +16819,7 @@ "risk": "medium", "title": "更新文档评论", "use_when": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ] }, { @@ -18289,6 +18291,7 @@ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], @@ -18312,7 +18315,7 @@ "use_when": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ] } diff --git a/internal/cli/schema_catalog/tools/doc.json b/internal/cli/schema_catalog/tools/doc.json index 7b9aef61..bc0a3fe6 100644 --- a/internal/cli/schema_catalog/tools/doc.json +++ b/internal/cli/schema_catalog/tools/doc.json @@ -2341,7 +2341,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc" @@ -2349,7 +2349,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc" }, @@ -2379,7 +2379,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -2391,7 +2391,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", @@ -2467,7 +2467,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -2478,7 +2478,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc create --name \"项目周报\" --format json", @@ -2572,7 +2572,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -2622,22 +2622,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ] } }, @@ -3335,8 +3335,8 @@ "source": "reviewed_command_registry", "title": "创建文档", "use_when": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ] }, "doc.create_file": { @@ -11416,7 +11416,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], @@ -11446,7 +11446,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "向文档插入块元素" @@ -11454,7 +11454,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "向文档插入块元素" }, @@ -11484,11 +11484,11 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ] @@ -11496,10 +11496,10 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ] @@ -11572,7 +11572,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -11583,7 +11583,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc block insert --node \u003cDOC_ID\u003e --text \"这是一段文字\" --format json", @@ -11671,7 +11671,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -11721,20 +11721,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ] } }, @@ -12876,7 +12878,8 @@ "source": "reviewed_command_registry", "title": "插入块元素", "use_when": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ] }, "doc.list_comments": { @@ -13811,7 +13814,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "查询文档一级块元素列表" @@ -13819,7 +13822,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "查询文档一级块元素列表" }, @@ -13849,7 +13852,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -13860,7 +13863,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "只要全文 Markdown 用 doc read", @@ -13935,7 +13938,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -13946,7 +13949,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc block list --node \u003cDOC_ID\u003e --format json", @@ -14040,7 +14043,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -14090,20 +14093,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ] } }, @@ -14747,7 +14750,7 @@ "source": "reviewed_command_registry", "title": "查询块元素", "use_when": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ] }, "doc.list_nodes": { @@ -37236,7 +37239,8 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "canonical_path": "doc.update_comment", "cli_name": "update", @@ -37255,7 +37259,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "更新指定文档评论的文字内容和可选 @用户/@群。" @@ -37263,7 +37267,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "更新指定文档评论的文字内容和可选 @用户/@群。" }, @@ -37287,20 +37291,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ] }, "canonical_path": { @@ -37389,7 +37395,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -37400,7 +37406,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc comment update --node \u003cDOC_ID\u003e --comment-key \u003cCOMMENT_KEY\u003e --content \"已按最新数据修正\" --format json", @@ -37488,7 +37494,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -37540,20 +37546,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ] } }, @@ -38078,7 +38084,7 @@ "source": "reviewed_command_registry", "title": "更新文档评论", "use_when": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ] }, "doc.update_document": { diff --git a/internal/cli/schema_catalog/tools/drive.json b/internal/cli/schema_catalog/tools/drive.json index e422fa92..434872f4 100644 --- a/internal/cli/schema_catalog/tools/drive.json +++ b/internal/cli/schema_catalog/tools/drive.json @@ -27245,6 +27245,7 @@ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], @@ -27268,7 +27269,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/drive.json", "value": "上传本地文件到钉盘或文档空间,或按节点 ID 确认覆盖已有文件" @@ -27276,7 +27277,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/drive.json", "value": "上传本地文件到钉盘或文档空间,或按节点 ID 确认覆盖已有文件" }, @@ -27300,13 +27301,14 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/drive.json", "value": [ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ] @@ -27314,12 +27316,13 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/drive.json", "value": [ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ] @@ -27432,7 +27435,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/drive.json", "value": [ @@ -27443,7 +27446,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/drive.json", "value": [ "dws drive upload --file ./report.pdf --format json", @@ -27531,7 +27534,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "selected": false, "source": "internal/cli/schema_hints/selection/drive.json", "value": true @@ -27583,25 +27586,25 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/drive.json", "value": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "source": "internal/cli/schema_hints/selection/drive.json", "value": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ] } @@ -28325,7 +28328,7 @@ "use_when": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ] } diff --git a/internal/cli/schema_hints/selection/doc.json b/internal/cli/schema_hints/selection/doc.json index 05068e13..76350ad7 100644 --- a/internal/cli/schema_hints/selection/doc.json +++ b/internal/cli/schema_hints/selection/doc.json @@ -84,8 +84,8 @@ "doc.create_document": { "agent_summary": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "use_when": [ - "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", - "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入明确要求的初始 Markdown/JSONML;用户显式要求正文 H1 时必须保留,不能用 --name 替代", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片;返回 nodeId 绑定同一请求的后续 list/insert/export,后续可观察操作仍须分别执行" ], "avoid_when": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type (勿用 doc create)", @@ -97,7 +97,7 @@ "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace --format json" ], "reviewed": true, - "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、显式正文 H1、同请求新 nodeId 绑定和可观察块操作边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source_refs": [ "CommandRegistry:canonical_path=doc.create_document", "cobra-help:dws doc create", @@ -372,10 +372,11 @@ "doc.insert_document_block": { "agent_summary": "向文档插入块元素", "use_when": [ - "在文档中插入新块(段落/标题等);简单场景用 --text/--heading,复杂块用 --element JSON" + "用户明确要求在文档中插入新块(段落/标题/列表等)时;简单段落/标题用 --text/--heading,复杂块用 --element JSON", + "用户要求有序列表块时使用 JSONML p.list.isOrdered=true(同一 listId)或等价原生 orderedList 结构,不能用普通 Markdown 代替" ], "avoid_when": [ - "整篇追加 Markdown 优先 doc update --mode append", + "仅在用户没有指定块操作、只要整篇追加 Markdown 时优先 doc update --mode append;显式 insert/标题块/列表块不能折叠", "插入本地文件附件优先 doc media insert", "删块用 block delete;改已有块用 block update" ], @@ -384,7 +385,7 @@ "dws doc block insert --node --heading \"二级标题\" --level 2 --format json" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐显式 block insert 的可观察操作语义和有序列表原生结构;不改变命令身份、参数契约、接口绑定或 Runtime 门禁。", "source_refs": [ "CommandRegistry:canonical_path=doc.insert_document_block", "cobra-help:dws doc block insert", @@ -421,7 +422,7 @@ "doc.list_document_blocks": { "agent_summary": "查询文档一级块元素列表", "use_when": [ - "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时" + "查看文档一级块结构、拿 blockId,供 insert/update/delete 或划词评论定位时;用户在显式工作流中点名 list 时必须真实执行并使用返回结果" ], "avoid_when": [ "只要全文 Markdown 用 doc read", @@ -432,7 +433,7 @@ "dws doc block list --node --start-index 0 --end-index 5 --format json" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 block list 的显式可观察步骤和真实 blockId 上下文传递;不改变命令身份、参数契约或接口绑定。", "source_refs": [ "CommandRegistry:canonical_path=doc.list_document_blocks", "cobra-help:dws doc block list", @@ -720,17 +721,18 @@ "doc.update_comment": { "agent_summary": "更新指定文档评论的文字内容和可选 @用户/@群。", "use_when": [ - "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id" + "修改已有评论正文;可选更新 --mention 或 --mentioned-open-conversation-id;执行后必须用 comment list 回查同一 commentKey 的目标字段" ], "avoid_when": [ - "删除评论用 delete;回复用 reply" + "删除评论用 delete;回复用 reply", + "响应为 null/空对象或回查仍是旧正文时不能判成功,必须报告更新未生效或部分完成" ], "examples": [ "dws doc comment update --node --comment-key --content \"已按最新数据修正\" --format json", "dws doc comment update --node --comment-key --content \"请群内确认\" --mentioned-open-conversation-id " ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐评论更新的业务结果与 comment list 回查语义;null/空响应不能单独证明成功,不改变命令身份、参数契约或接口绑定。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.update_comment", "cobra-help:dws doc comment update --help", diff --git a/internal/cli/schema_hints/selection/drive.json b/internal/cli/schema_hints/selection/drive.json index 6fd18126..d7318cb1 100644 --- a/internal/cli/schema_hints/selection/drive.json +++ b/internal/cli/schema_hints/selection/drive.json @@ -911,13 +911,14 @@ "use_when": [ "用户要把本地文件上传到钉盘/我的文件(首选一条命令自动完成凭证+PUT+提交)时", "用户明确要求只上传或暂存附件、暂时不要发送到任何聊天会话时", - "上传到知识库/文档空间时加 --workspace;需要转在线文档时加 --convert", + "用户只要保留原始文件供存储或下载时使用;上传到知识库/文档空间时可加 --workspace", "用户明确要求用本地文件替换已有钉盘/文档空间文件时传 --node;该模式会覆盖远端内容并要求确认" ], "avoid_when": [ "用户要把文件发送到群聊或单聊时使用 chat message send --msg-type file --file-path;drive upload 不会发送聊天消息", "常规场景不要拆成 upload-info + 手动 PUT + commit;仅自定义流式上传才用三步", "要把文件作为文档正文附件插入改用 dws doc media insert", + "Word/Excel/Markdown 要求上传后在线编辑、大家直接在线改或转钉钉文档时改用 dws doc import;普通 drive upload 返回 docx/xlsx 文件不能宣称可在线编辑", "用户明确说文档空间且走 doc 兼容入口时可用 dws doc upload,默认仍推荐本命令", "用户没有明确同意替换目标文件时不要使用 --node;新建上传应使用 --folder 或目标根目录" ], @@ -926,7 +927,7 @@ "dws drive upload --file ./README.md --node --format json" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐普通文件存储与在线文档导入边界:在线编辑需求硬路由 doc import,drive upload 不承诺转换结果;不改变命令身份、参数契约或接口绑定。", "source_refs": [ "CommandRegistry:canonical_path=drive.upload", "cobra-help:dws drive upload", diff --git a/skills/mono/references/best_practices/04-document.md b/skills/mono/references/best_practices/04-document.md index c884341e..df86a479 100644 --- a/skills/mono/references/best_practices/04-document.md +++ b/skills/mono/references/best_practices/04-document.md @@ -2,6 +2,13 @@ > 通用规范见 [_common/conventions.md](_common/conventions.md)。 +## 显式工作流与事实保真 + +- 用户点名的 `create → list → insert/append/update` 是可观察命令链,必须保持顺序逐项执行;create 只承载明确的初始正文。有序列表块必须验证回读结构中的 `list.isOrdered=true`。 +- `--name` 不替代用户显式要求的正文 H1;新建资源返回 ID 后,同一请求的指代绑定该新资源,禁止搜索同名旧资源替换。 +- Word/Excel 需要“在线编辑/直接在线改”时使用 `doc import`,普通 `drive upload` 只保留原文件。 +- 汇总时保留证据强度:验证数量不等于通过数量,整理问题不等于根因分析。任一步骤返回 `null`/空结果或回查不一致时只能报告部分完成。 + | Recipe | 行动指南(固定路线) | |--------|-------------------| | write-doc | 1. 按[「多源并行采集」](_common/conventions.md#多源并行采集公共模式)执行
2. **先把内容写入临时文件**(Linux/Mac `/tmp/.md`,Windows `%TEMP%\.md`)—— 含多行/表格/长文本必须走文件,不要把 markdown 直接作为命令行字符串
3. **单步创建**(< 200KB):`doc create --name "<文档名>" --content-file [--folder ] [--workspace ]`(`--folder` 只传文档文件夹 nodeId / alidocs 文件夹 URL,不传数字 dentryId)
4. **超长兜底**(> 200KB):**必须先向用户提示截断风险**(详见下方「分块 append 截断风险提示」),用户确认后再执行:`doc create --name "<文档名>" [--folder/--workspace]` → `nodeId` → 按段落切 ≤200KB 片段(不断表格) → 每片 `doc update --node --content-file --mode append`
5. **回读校验**(必须):所有写入完成后,执行 `doc read --node ` 回读文档,校验关键标题/段落是否完整写入(详见下方「doc update 回读校验规范」)
备选(仅短内容 <2KB 且无换行/表格):`doc create --name "..." --content "..."` | diff --git a/skills/mono/references/products/doc.md b/skills/mono/references/products/doc.md index 767507d0..5352b5f1 100644 --- a/skills/mono/references/products/doc.md +++ b/skills/mono/references/products/doc.md @@ -665,8 +665,8 @@ Flags: - 知识库内 → `dws wiki node create --workspace --type folder`(`doc folder create` / `doc file create --type folder` 已弃用) 用户说"上传文件/传文件/上传到文档/上传到知识库": -- 上传 → `upload`(需本地文件路径) -- 上传并转换 → `upload --convert` +- 仅保留原始文件用于存储/下载 → `drive upload`(需本地文件路径) +- 用户明确要求“在线编辑/大家直接在线改/转在线文档” → `doc import --file <本地路径>`;不得用普通 upload 的成功响应宣称可在线编辑 用户说"导入文件/导入为在线文档/导入 Word/导入 Excel/导入 xmind/导入 Markdown/把本地文件转在线文档": - 导入并转换为在线文档 → `doc import --file <本地路径>` @@ -742,8 +742,8 @@ Flags: 关键区分: doc(文档编辑/阅读) vs aitable(数据表格操作) vs drive(钉盘文件管理) 用户说"上传文件/传文件/上传到文档/上传到知识库": -- 上传 → `upload`(需本地文件路径) -- 上传并转换 → `upload --convert` +- 仅保留原始文件用于存储/下载 → `drive upload`(需本地文件路径) +- 要转换为可在线编辑文档 → `doc import --file <本地路径>`,导入后验证在线类型与目标文件夹 用户说"下载文件/导出文件/下载到本地": - 下载 → `download`(需文件节点 ID 或 URL) @@ -1050,14 +1050,18 @@ EOF - `read` 返回的内容中,文档里的附件会以 OSS 临时下载链接形式给出(如 `https://alidocs2.oss-cn-zhangjiakou.aliyuncs.com/res/.../att/.ext?Expires=...`),该链接会过期。链接过期后,可从 URL 路径中提取 ``(即 `/att/` 后、扩展名前的 UUID 部分),然后使用 `media download --node --resource-id ` 重新获取下载链接 - `create` 不传 `--folder` 和 `--workspace` 时,默认创建在"我的文档"根目录 - `create` 只能建"文档"(adoc);要建表格/脑图/白板/多维表/演示,用 `dws wiki node create --workspace --type `(`doc file create` 已弃用);建普通文件夹用 `dws drive mkdir` -- `block list/insert/update/delete` 是块级精细编辑,适合结构化修改;简单内容追加建议用 `update --mode append` +- `block list/insert/update/delete` 是块级精细编辑,适合结构化修改;只有用户未指定块操作的纯文本追加才建议 `update --mode append`。用户点名 list/insert/update/append 时必须逐项真实调用,不得折叠进 create - `block insert` 优先使用 `--text` 或 `--heading` 快捷方式;复杂块类型 (table, callout 等) 使用 `--element` JSON +- 用户要求“有序列表块”时必须写真实列表结构(JSONML `p.list.isOrdered=true` 或等价 orderedList element),普通 Markdown/数字前缀段落不算完成 - `--content` 参数中的换行必须使用**真实换行符**(即实际的换行字符,Unicode `U+000A`),而不是字面量字符串 `\n`(反斜杠加字母 n)。在通过程序或大模型构造此参数时,请确保字符串在发送前已正确反转义。如果传入的是两个字符的字面量 `\n`,所有内容将渲染在同一行,导致标题、段落和表格格式全部错乱。**含多行/表格/长文本时优先用 `--content-file path.md` 或 `--content -`(stdin),不经过 shell escape,换行和表格都保持原样**(详见下方「长 Markdown 写入」)。 - 块类型包括: paragraph, heading, blockquote, callout, columns, orderedList, unorderedList, table, sheet, attachment, slot - 关键区分: doc(文档内容级操作) vs wiki(知识库空间级管理) vs aitable(数据表格操作) vs drive(钉盘文件管理) - wiki 是知识库容器,doc 是知识库中的文档内容;需要 `workspaceId` 时,先用 `dws wiki space list/search` 获取,再传给 doc 的 `--workspace` 参数 -- `doc upload vs drive upload`:用户提到"知识库/文档空间/workspace" → `doc upload`;提到"钉盘/网盘/我的文件" → `drive upload`;未明确目标时默认 `drive upload` -- `upload` 支持上传任意类型文件 (PDF、Office、图片等) 到钉钉文档空间或知识库;`--convert` 可将 Office 文件转换为钉钉在线文档 +- `drive upload` / `doc upload` 是普通文件存储路径;用户要求 Word/Excel “在线编辑/直接在线改”时硬路由到 `doc import`,并验证导入后的在线类型和文件夹。只有用户明确同时要原文件与在线版时才分别 upload + import +- 同一请求中新建、复制或导入返回的 `nodeId` 必须绑定后续“这篇/刚才那篇/上次那篇”;禁止搜索同名旧资源覆盖绑定 +- `--name` 只是文档外壳标题,不能替代用户显式要求的正文 H1;用户说“正文先起一级标题”时必须写入或插入真实 H1 +- 汇总只能保持用户事实强度:“验证 12 条”不等于“12 条全部通过”,“整理问题清单”不等于“输出根因分析” +- 写操作响应为 `null`/空对象或回查未变化时,该步骤失败;必须报告部分完成,禁止用其他成功步骤把整体说成“全部完成” - `upload` 是三步自动完成的流程 (获取凭证 → OSS 上传 → 提交入库),无需手动分步操作 - `download` 是两步自动完成的流程 (获取下载链接 → HTTP GET 下载),支持自动推断文件名;`--output` 可指定文件路径或目录 - `media insert` 是三步自动完成的流程 (获取附件上传凭证 → OSS 上传 → 插入附件块到文档),无需手动分步操作 diff --git a/skills/mono/references/products/doc/doc-block.md b/skills/mono/references/products/doc/doc-block.md index 04e97ac2..e2a6ca30 100644 --- a/skills/mono/references/products/doc/doc-block.md +++ b/skills/mono/references/products/doc/doc-block.md @@ -10,6 +10,8 @@ > **改写已有文档优先 JSONML**:保真度最高、callout / 分栏 / 表格 / @人 / 附件 / 颜色 / 嵌套都能 1:1 round-trip;写入端有 validator 兜底。详见 [`./style/doc-update-workflow.md` §1.3 编辑形态优先级](./style/doc-update-workflow.md)。 +> **显式块操作不可折叠**:用户说“先 create,再 list/insert/update/append”时按原顺序真实调用;不能因为最终正文相似,就把后续块操作合并进 create 或一次 Markdown 写入。 + --- ## doc block list(查询块元素) @@ -173,7 +175,8 @@ dws doc block delete --node DOC_ID --block-id UUID - **块类型**:paragraph、heading、blockquote、callout、columns、orderedList、unorderedList、table、sheet、attachment、slot。 - **快捷 vs --element**:`block insert` 优先使用 `--text` 或 `--heading` 快捷方式;复杂块类型(table、callout、columns 等)使用 `--element` JSON 或 `--content-format jsonml`。 -- **简单内容追加**:建议用 [`./doc-update.md`](./doc-update.md) `--mode append`,不必走 block insert。 +- **有序列表块**:用户明确要求 ordered list / 有序列表块时,必须用 JSONML `p` 节点的 `list.isOrdered=true`(同一 `listId`;仅首项设 `start:1`)或等价原生 orderedList element;带 `1.` 前缀的普通段落、普通 Markdown 或一次 create 不满足要求。 +- **简单内容追加**:用户只说追加纯文本且不强调块操作时可用 [`./doc-update.md`](./doc-update.md) `--mode append`;用户明确说 block insert / 插入段落 / 插入标题 / 插入列表块时必须走 block insert。 - **JSONML validator**(写入端默认行为): - 裸字符串、缺 uuid 等结构错误会被 validator 抦下并返回带 path 的错误(如 `$[2][2]: paragraph child must be span wrapper, got raw string.`)。 - `--fix-jsonml` 开启 JSON 语法修复,推荐 agent 调用。 @@ -241,6 +244,12 @@ dws doc block list --node --content-format jsonml --block-id dws doc block insert --node --content-format jsonml --ref-block --where after \ --element '["p",{},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"新段落"]]]' +# 插入有序列表块(3 项共用 listId,仅首项有 start) +dws doc block insert --node --content-format jsonml \ + --element '["p",{"uuid":"ol1","list":{"listId":"actions","level":0,"isOrdered":true,"start":1}},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"第一项"]]]' +dws doc block insert --node --content-format jsonml \ + --element '["p",{"uuid":"ol2","list":{"listId":"actions","level":0,"isOrdered":true}},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"第二项"]]]' + # 插入 callout(colorBlocks) dws doc block insert --node --content-format jsonml --ref-block --where after \ --element '["container",{"uuid":"co1","subType":"colorBlocks","metadata":{"bgcolor":"#FDE2E0","border":"#F5C2C7"}},["p",{"uuid":"co1p1"},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"高风险操作,先备份"]]]]' diff --git a/skills/mono/references/products/doc/doc-comment.md b/skills/mono/references/products/doc/doc-comment.md index 77edc1c6..9f7c5f5c 100644 --- a/skills/mono/references/products/doc/doc-comment.md +++ b/skills/mono/references/products/doc/doc-comment.md @@ -131,6 +131,7 @@ Flags: - 划词评论的 `--start` / `--end` 是块内文本字符偏移量,从 0 开始;通过 [`./doc-block.md`](./doc-block.md) `block list` 取 `paragraph.text` 后人工或脚本计算。 - `reply` 加 `--emoji` 时 `--content` 填表情名称(如 `比心`、`赞`),不是文字内容。 - `reply --emoji` 不能同时 @群。 +- `comment create/reply/update/delete` 的退出码 0 不等于业务成功。响应为 `null`、空对象或缺少可核验字段时,立即执行 `comment list` 回查目标 `commentKey`。若 update 后正文仍是旧值,必须判定“更新未生效”;即使其他步骤成功或评论随后被删除,也只能报告部分完成,禁止写“全部完成”。 ## 上下文传递 diff --git a/skills/mono/references/products/doc/doc-create.md b/skills/mono/references/products/doc/doc-create.md index f3f311f3..516f0517 100644 --- a/skills/mono/references/products/doc/doc-create.md +++ b/skills/mono/references/products/doc/doc-create.md @@ -40,7 +40,7 @@ Flags: ## 关键说明 -- **`--name` 是 H1**:正文从 `##` 开始;正文内不要再写 `#` 一级标题(除非确需且已说明动机)。 +- **标题优先级**:`--name` 是文档外壳标题,默认可视作 H1;但它不能替代用户显式要求的正文一级标题。用户说“正文写 `# ...`”“正文先起个一级标题”时,必须在初始内容中保留该 `#` H1;用户未要求正文 H1 时,正文默认从 `##` 开始以避免重复。 - 不传 `--folder` 和 `--workspace` 时,默认创建在「我的文档」根目录。 - `--folder` 仅接受文档文件夹 `nodeId` / `dentryUuid` / alidocs 文件夹 URL;**禁止**传入 drive `dentryId`、`parentId`、`spaceId` 这类纯数字 ID。 - 输入方式选择见 [`./doc-update.md` §内容写入管道](./doc-update.md#内容写入管道createupdate-共用)(与 update 共用)。短文本字面量可 `--content`,多行/表格/特殊字符必须 `--content-file` 或 `--content -`。 @@ -54,6 +54,12 @@ Flags: | `docUrl` | 最终交付给用户的链接;缺失时用 [`./doc-info.md`](./doc-info.md) 补查 | | `chunksWritten` | 判断是否触发自动分片;> 1 时重点检查章节顺序 | +同一请求后续出现“这篇/刚才那篇/上次那篇”时,直接续用本次 create 返回的 `nodeId`;禁止先搜索同名文档再把后续操作指向旧节点。 + +## 显式操作序列 + +用户点名 `block list`、插入、追加、更新等后续动作时,必须按原顺序逐项执行。`doc create` 只写用户指定的初始内容,不能为了减少调用把后续标题、列表或段落提前塞进 create。例:`创建 → 查看块结构 → 末尾插入段落` 必须真实执行 create、block list、block insert 三步。 + ## 回读验收(必读) CLI **不会**自动回读校验。**每次创建后**都必须执行 `doc read --node ` 校验关键标题、段落首句、表格表头是否完整。详见 [`./style/doc-create-workflow.md` «回读验收»](./style/doc-create-workflow.md)。 diff --git a/skills/mono/references/products/doc/doc-export.md b/skills/mono/references/products/doc/doc-export.md index 0abbeedf..97321c78 100644 --- a/skills/mono/references/products/doc/doc-export.md +++ b/skills/mono/references/products/doc/doc-export.md @@ -45,6 +45,7 @@ Flags: ## 关键说明 +- 同一请求中刚执行 create/copy/import 并紧接着说“这篇/刚才那篇/上次那篇”时,`--node` 必须使用该写操作真实返回的新 `nodeId`;不得预先搜索同名文档,也不得用搜索结果中的旧节点替换它。 - `export` 是一体化命令,一条命令自动完成提交→轮询→下载,**无需手动编排轮询**。CLI 内部使用渐进式退避轮询(最多约 5 分钟)。 - `export` 超时或中断后,CLI 会输出 `jobId`,可用 `dws doc export get --job-id ` 手动查询任务状态。 - `export` 当前仅支持钉钉在线文档(alidocs,`contentType=ALIDOC`)导出为 `docx`,**在线表格导出请使用其他命令**。 diff --git a/skills/mono/references/products/doc/doc-file-ops.md b/skills/mono/references/products/doc/doc-file-ops.md index 6ed912b2..168644c7 100644 --- a/skills/mono/references/products/doc/doc-file-ops.md +++ b/skills/mono/references/products/doc/doc-file-ops.md @@ -32,6 +32,7 @@ Flags: - `upload` 是三步自动完成的流程(获取凭证 → OSS 上传 → 提交入库),无需手动分步操作。 - 支持上传任意类型文件(PDF、Office、图片等)到钉钉文档空间或知识库。 - `--convert` 可将 Office 文件转换为钉钉在线文档。 +- **在线编辑硬路由**:用户说“大家直接在线改/上传后在线编辑/转成钉钉文档”时使用 [`./doc-import.md`](./doc-import.md) `doc import`,并回查在线类型;普通 `doc/drive upload` 只用于保留文件,不能据此承诺可在线编辑。 - **`doc upload` vs `drive upload`**:用户提到「知识库 / 文档空间 / workspace」→ `doc upload`;提到「钉盘 / 网盘 / 我的文件」→ `drive upload`;未明确目标时默认 `drive upload`。 - 与 [`./doc-media.md`](./doc-media.md) `media insert` 的区别:`upload` 上传到文档空间作为**独立文件**;`media insert` 作为**附件块插入到文档正文中**。 diff --git a/skills/mono/references/products/doc/doc-import.md b/skills/mono/references/products/doc/doc-import.md index bd6291de..18cd3b70 100644 --- a/skills/mono/references/products/doc/doc-import.md +++ b/skills/mono/references/products/doc/doc-import.md @@ -6,6 +6,8 @@ 不要先读取文件内容再调用 `doc create` 或 `doc update`。`doc import` 会按文件格式走导入任务,保留更完整的原始结构。 +> **在线编辑硬路由**:用户说“上传后在线编辑/大家直接在线改/转成钉钉文档”时必须使用 `doc import`。`drive upload` 只保留原始 `.docx/.xlsx/...` 普通文件,不能据此宣称已可在线编辑。若用户明确要同时保留原文件和在线版,才先 `drive upload`,再单独 `doc import`,并分别验证两个返回节点。 + ## 命令 ```bash @@ -38,6 +40,7 @@ dws doc import get --task-id --format json 3. 执行 `dws doc import --file ... --format json`。 4. 正常情况下 CLI 会自动提交、上传并轮询导入任务。 5. 如果命令超时或中断,从输出中提取 `taskId`,再执行 `dws doc import get --task-id --format json`。 +6. 用返回的 `documentUrl`/`nodeId` 执行 `drive info` 或 `doc info`,确认在线类型和目标文件夹;验证通过后才能说“可直接在线编辑”。 ## 上下文传递 diff --git a/skills/mono/references/products/doc/style/doc-create-workflow.md b/skills/mono/references/products/doc/style/doc-create-workflow.md index e055629e..77440175 100644 --- a/skills/mono/references/products/doc/style/doc-create-workflow.md +++ b/skills/mono/references/products/doc/style/doc-create-workflow.md @@ -8,7 +8,7 @@ > **同时读取 [doc-style-guideline.md](./doc-style-guideline.md):** > - **§2.0 类型判断决策表** → 锁定文档类型(决策型 / 执行型 / 说明型 / 知识沉淀型)和骨架 -> - **§1 硬规则** → 全程生效(`--name` 已是 H1、不编造 URL、Markdown 草稿不写 callout 等) +> - **§1 硬规则** → 全程生效(用户显式正文 H1 优先、不编造 URL、Markdown 草稿不写 callout 等) ### 关键词速查(用户意图 → 起稿路径) @@ -274,7 +274,7 @@ callout 可通过 `"showstk": true, "sticker": "图标名"` 配置顶部贴纸 ``` - 根节点固定 `"root"`(不是 `"body"`) -- `--name` 已是 H1,JSONML 从 `h2` 开始 +- 用户未要求正文 H1 时,JSONML 从 `h2` 开始;用户明确要求“正文一级标题/插入一级标题”时必须构造 `h1` - 表格结构是 `table → tr → tc`(无 `th`/`td`) - 分栏是 `table` + `"sr": true`,`tc` 建议设 `fill` 背景色 - 有序列表:仅第一项设 `"start": 1`,后续项不设 `start`(系统自动递增) @@ -315,7 +315,7 @@ dws doc read --node --content-format jsonml --output /tmp/-readba - 只使用用户已提供或对话中已确认的正文素材。 - 如果正文素材不足,先补齐文档目标、受众、章节和缺口;不要在本文中临时扩展跨产品采集流程。 - **先按 [doc-style-guideline.md §2.0 类型判断决策表](./doc-style-guideline.md) 确定文档类型,再用对应类型的骨架样板(§2.1 决策型 / §2.2 执行型 / §2.3 说明型 / §2.4 知识沉淀型)**。不要套通用三段式。 -- **`--name` 已是 H1,正文从 `##` 开始**;正文内不要再写 `#` 一级标题(除非确实需要正文内再造一级 H1 并说明动机)。 +- **`--name` 是外壳标题,不覆盖显式正文 H1**:用户未要求正文一级标题时从 `##` 开始;用户明确给出 `# ...` 或要求“先起一级标题”时,正文必须保留该 H1。 - 摘要、bullet、引用块、callout 等元素的使用边界以 style-guideline §3-§7 为准。 - 同类信息保持一致:风险、状态、行动项各用一种元素 + 一种视觉语义(style-guideline §1.2 / §5)。 - 临时文件必须保留真实换行,不能把换行写成字面量 `\n`。 diff --git a/skills/mono/references/products/doc/style/doc-style-guideline.md b/skills/mono/references/products/doc/style/doc-style-guideline.md index 1e00cad5..e1162376 100644 --- a/skills/mono/references/products/doc/style/doc-style-guideline.md +++ b/skills/mono/references/products/doc/style/doc-style-guideline.md @@ -25,7 +25,7 @@ ## 一、硬规则 -1. **`--name` 是 H1**:正文从 `##` 开始;正文内不写 `#`(除非确需正文内再造一级 H1 并说明动机) +1. **用户显式正文 H1 优先**:`--name` 是文档外壳标题;用户未要求正文一级标题时从 `##` 开始。用户明确说“正文写 `# ...` / 先起一级标题 / 插入一级标题”时必须保留或插入真实 H1,不得用 `--name` 代替 2. **同类信息同表达**:风险、状态、行动项、证据,每类只用一种元素 + 一种视觉语义(见 §5) 3. **Markdown 草稿阶段只用稳定元素**:标题、段落、列表、checklist、表格、代码块;callout / 分栏 / 附件 / 复杂嵌套留到创建后用 `doc block insert` / `doc media insert` 精修 4. **引用块只用于原文**:用户原话、会议摘录、外部材料原文;不许包装作者自己的结论 @@ -209,7 +209,7 @@ ### 4.1 标题与段落 -- 正文从 `##` 开始(H1 已被 `--name` 占用) +- 用户未要求正文 H1 时从 `##` 开始;用户明确要求正文 H1 时按原文使用 `#` 或 heading level 1 - 标题层级 ≤ 4 层(§7) - 单段过长先拆段,再考虑换元素 @@ -217,6 +217,7 @@ - 普通列表:并列要点 - 有序列表:顺序步骤 +- 用户明确要求“有序列表块”时必须使用真实列表结构;JSONML 为带 `list.isOrdered=true` 的多个 `p` 节点,不能只写带数字前缀的普通段落或以整篇 Markdown 代替显式 block insert - checklist:待办状态(含 `- [ ]` / `- [x]`) 列表项里开始出现"负责人 / 截止时间 / 状态"这类字段时,改用表格。 diff --git a/skills/mono/scripts/doc_create_and_write.py b/skills/mono/scripts/doc_create_and_write.py index 367e4b93..4f2d9f29 100644 --- a/skills/mono/scripts/doc_create_and_write.py +++ b/skills/mono/scripts/doc_create_and_write.py @@ -1,181 +1,183 @@ #!/usr/bin/env python3 -""" -在指定目录创建文档并写入 Markdown 内容(一键完成) +"""用原生 dws 写入管道创建文档,并回读验证。""" -用法: - python doc_create_and_write.py \ - --name "项目周报" \ - --content "# 本周总结\n\n## 完成事项\n- 任务A" +from __future__ import annotations - python doc_create_and_write.py \ - --name "会议纪要" \ - --content-file notes.md - - python doc_create_and_write.py \ - --name "知识库文档" --content "# 内容" --folder FOLDER_ID - - python doc_create_and_write.py --name "test" --content "hello" --dry-run -""" - -import sys -import json -import time -import subprocess import argparse +import json +import shlex +import subprocess +import sys +import tempfile from pathlib import Path -from typing import List, Any, Optional +from typing import Any, Optional, Sequence -def run_dws( - args: List[str], dry_run: bool = False, -) -> Optional[Any]: - cmd = ['dws'] + args +class ScriptError(RuntimeError): + """可预期的脚本执行错误。""" + + +def decode_json_output(output: str) -> Any: + """解析 JSON;兼容长内容写入前置的进度行。""" + text = output.strip() + if not text: + raise ScriptError("dws 未返回 JSON") + try: + return json.loads(text) + except json.JSONDecodeError: + decoder = json.JSONDecoder() + for offset, character in enumerate(text): + if character not in "[{": + continue + try: + value, end = decoder.raw_decode(text, offset) + except json.JSONDecodeError: + continue + if not text[end:].strip(): + return value + raise ScriptError("dws 返回的不是合法 JSON") + + +def run_dws(args: Sequence[str], dry_run: bool = False) -> Any: + """执行一条 dws 命令,并把命令/业务失败统一转成 ScriptError。""" + command = ["dws", *args] if dry_run: - print(f"[dry-run] {' '.join(cmd)}") - return {'dry_run': True} + print(f"[dry-run] {shlex.join(command)}") + return {"dry_run": True} try: result = subprocess.run( - cmd, capture_output=True, text=True, timeout=60 + command, + capture_output=True, + text=True, + timeout=120, + check=False, ) - if result.returncode != 0: - print(f" ✗ 错误:{result.stderr.strip()}") - return None - return json.loads(result.stdout) - except (subprocess.TimeoutExpired, json.JSONDecodeError, - FileNotFoundError) as e: - print(f" ✗ 错误:{e}") - return None + except (subprocess.TimeoutExpired, FileNotFoundError) as exc: + raise ScriptError(f"执行 dws 失败:{exc}") from exc + if result.returncode != 0: + detail = result.stderr.strip() or result.stdout.strip() + raise ScriptError( + f"dws 命令失败:{detail or f'退出码 {result.returncode}'}" + ) + data = decode_json_output(result.stdout) + if data is None or data == {}: + raise ScriptError("dws 返回空业务结果,无法确认操作成功") + if isinstance(data, dict) and data.get("success") is False: + detail = data.get("errorMsg") or data.get("message") or "未知错误" + raise ScriptError(f"dws 业务调用失败:{detail}") + return data -def run_dws_with_retry( - args: List[str], - dry_run: bool = False, - max_retries: int = 3, - retry_delay: float = 1.0, -) -> Optional[Any]: - """带重试机制的 dws 命令执行""" - last_error = None - for attempt in range(1, max_retries + 1): - result = run_dws(args, dry_run=dry_run) - if result is not None: - return result - if attempt < max_retries: - print(f" ⚠️ 第 {attempt} 次尝试失败,{retry_delay}秒后重试...") - time.sleep(retry_delay) - retry_delay *= 1.5 # 指数退避 - return None +def first_value(payload: Any, keys: Sequence[str]) -> str: + """从嵌套响应中提取第一个非空稳定字段。""" + if isinstance(payload, dict): + for key in keys: + value = payload.get(key) + if value is not None and str(value).strip(): + return str(value).strip() + for value in payload.values(): + found = first_value(value, keys) + if found: + return found + elif isinstance(payload, list): + for value in payload: + found = first_value(value, keys) + if found: + return found + return "" -def main(): +def run(argv: Optional[Sequence[str]] = None) -> int: parser = argparse.ArgumentParser( - description='创建文档并写入内容' + description="使用 dws doc create 创建文档并回读验证" ) - parser.add_argument('--name', required=True, help='文档名称') - parser.add_argument('--content', default='', help='Markdown 内容') - parser.add_argument('--content-file', default='', help='内容文件') - parser.add_argument('--folder', default='', help='目标文件夹 ID 或 URL') - parser.add_argument('--workspace', default='', help='目标知识库 ID') - parser.add_argument( - '--mode', default='append', choices=['overwrite', 'append'], - help='写入模式: overwrite=覆盖, append=追加 (默认 append)', + parser.add_argument("--name", required=True, help="文档名称") + content_group = parser.add_mutually_exclusive_group(required=True) + content_group.add_argument("--content", help="Markdown 内容") + content_group.add_argument("--content-file", help="UTF-8 Markdown 文件") + location_group = parser.add_mutually_exclusive_group() + location_group.add_argument( + "--folder", default="", help="目标文档文件夹 ID 或 URL" ) - parser.add_argument( - '--max-retries', type=int, default=3, - help='每块写入失败时的最大重试次数 (默认 3)', + location_group.add_argument( + "--workspace", default="", help="目标知识库 ID 或 URL" ) - parser.add_argument('--dry-run', action='store_true') - args = parser.parse_args() + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args(argv) - content = args.content + supplied_path: Optional[Path] = None + temporary_path: Optional[Path] = None if args.content_file: - p = Path(args.content_file) - if not p.exists(): - print(f"错误:文件不存在: {p}") - sys.exit(1) - content = p.read_text(encoding='utf-8') - if not content: - print('错误:需要 --content 或 --content-file') - sys.exit(1) - chunk_size = 30000 + supplied_path = Path(args.content_file) + if not supplied_path.is_file(): + raise ScriptError(f"内容文件不存在:{supplied_path}") + elif not args.content or not args.content.strip(): + raise ScriptError("--content 不能为空") - create_args = ['doc', 'create', '--name', args.name, '--format', 'json'] - if args.folder: - create_args.extend(['--folder', args.folder]) - if args.workspace: - create_args.extend(['--workspace', args.workspace]) + try: + if supplied_path is None and not args.dry_run: + with tempfile.NamedTemporaryFile( + mode="w", encoding="utf-8", suffix=".md", delete=False + ) as handle: + handle.write(args.content) + temporary_path = Path(handle.name) + supplied_path = temporary_path - print(f'\n📝 创建文档: {args.name}') - create_data = run_dws(create_args, dry_run=args.dry_run) + content_path = str(supplied_path) if supplied_path else "" + create_args = [ + "doc", "create", + "--name", args.name, + "--content-file", content_path, + "--content-format", "markdown", + "--format", "json", + ] + if args.folder: + create_args.extend(["--folder", args.folder]) + if args.workspace: + create_args.extend(["--workspace", args.workspace]) - node_id = None - if not args.dry_run: - if not create_data: - sys.exit(1) - node_id = (create_data.get('nodeId') - or create_data.get('dentryUuid') - or create_data.get('id', '')) - print(f" ✓ 文档已创建 (ID: {node_id})") + created = run_dws(create_args, dry_run=args.dry_run) + node_id = "" if args.dry_run else first_value( + created, ("nodeId", "dentryUuid") + ) + if not node_id: + raise ScriptError("文档创建响应缺少 nodeId,无法验证") - if len(content) <= chunk_size: - mode_label = '追加' if args.mode == 'append' else '覆盖' - print(f'\n✍️ 写入内容 (模式: {mode_label}, {len(content)} 字符)...') - write_data = run_dws([ - 'doc', 'update', - '--node', node_id or '', - '--content', content, - '--mode', args.mode, - '--format', 'json', - ], dry_run=args.dry_run) - if write_data: - print(f" ✓ 内容已写入 ({len(content)} 字符)") - else: - chunks = [] - pos = 0 - while pos < len(content): - end = min(pos + chunk_size, len(content)) - if end < len(content): - newline_pos = content.rfind('\n', pos, end) - if newline_pos > pos: - end = newline_pos + 1 - chunks.append(content[pos:end]) - pos = end + info = run_dws( + ["doc", "info", "--node", node_id, "--format", "json"], + dry_run=args.dry_run, + ) + readback = run_dws( + ["doc", "read", "--node", node_id, "--format", "json"], + dry_run=args.dry_run, + ) + if args.dry_run: + return 0 + if not first_value(readback, ("markdown", "jsonml", "content")): + raise ScriptError("文档回读未返回正文,无法确认写入成功") - total_chunks = len(chunks) - print(f'\n✍️ 内容较长 ({len(content)} 字符), 分 {total_chunks} 块写入...') - - success_chunks = 0 - for idx, chunk in enumerate(chunks): - chunk_mode = args.mode if idx == 0 else 'append' - write_data = run_dws_with_retry( - [ - 'doc', 'update', - '--node', node_id or '', - '--content', chunk, - '--mode', chunk_mode, - '--format', 'json', - ], - dry_run=args.dry_run, - max_retries=args.max_retries, - ) - if write_data: - print(f" ✓ 块 {idx + 1}/{total_chunks} 已写入 ({len(chunk)} 字符)") - success_chunks += 1 - elif not args.dry_run: - # 写入失败,报告部分写入状态 - print(f"\n❌ 块 {idx + 1}/{total_chunks} 写入失败(已重试 {args.max_retries} 次)") - print(f"\n⚠️ 文档处于部分写入状态:") - print(f" - 文档 ID: {node_id}") - print(f" - 已写入: {success_chunks}/{total_chunks} 块") - print(f" - 失败位置: 第 {idx + 1} 块") - if args.mode == 'overwrite': - print(f" - 模式: 覆盖模式,文档可能包含不完整内容") - print(f" - 建议: 手动检查文档内容,或删除后重新创建") - else: - print(f" - 模式: 追加模式,已写入内容已保存") - print(f" - 建议: 可手动补充剩余内容,或重新运行脚本") - sys.exit(1) - print('\n✅ 完成!') + summary = { + "success": True, + "nodeId": node_id, + "docUrl": first_value(info, ("docUrl", "documentUrl", "url")) + or first_value(created, ("docUrl", "documentUrl", "url")), + "chunksWritten": first_value(created, ("chunksWritten",)), + "verified": True, + } + print(json.dumps(summary, ensure_ascii=False)) + return 0 + finally: + if temporary_path is not None: + temporary_path.unlink(missing_ok=True) -if __name__ == '__main__': +def main() -> None: + try: + raise SystemExit(run()) + except ScriptError as exc: + print(f"错误:{exc}", file=sys.stderr) + raise SystemExit(1) from exc + + +if __name__ == "__main__": main() diff --git a/skills/multi/dingtalk-doc/SKILL.md b/skills/multi/dingtalk-doc/SKILL.md index 19211b63..356bcde0 100644 --- a/skills/multi/dingtalk-doc/SKILL.md +++ b/skills/multi/dingtalk-doc/SKILL.md @@ -40,6 +40,7 @@ metadata: | 块 | `blockId` / JSONML `uuid` 必须来自 `block list`,更新节点的 uuid 必须与目标块一致 | | 评论 | `commentKey` 来自评论 list/create;划词评论还需同一块的真实 `start/end` | | 异步任务 | 导出 `jobId` 与导入 `taskId` 只查询对应任务,不能替代 nodeId | +| 新建资源续用 | 同一请求中 create/mkdir/import/copy 返回的新 `nodeId` / `fileId` 立即成为后续“这篇/刚才那篇/上次那篇/这个文件夹”的目标;禁止再按同名搜索并改用旧资源 | | 内容格式 | Markdown 适合线性正文;已有富结构优先 JSONML/块级编辑,禁止用 Markdown overwrite 误称保真 | | 普通文件 | adoc 才用 `doc read/export`;`.md`、axls、able 和普通文件按真实 `extension` 切对应 Skill | @@ -52,22 +53,27 @@ metadata: | 按名称找文档 | `+find-doc --query <关键词>`;需最近访问/扩展名/创建者等过滤用 `+search` | 候选不唯一先消歧;随后 `drive info --node ` 判 `extension` | | 读取 adoc | `drive info --node ` → `doc read --node ` | 用户已给 nodeId/URL 时不再搜索;非 adoc 不调用 `doc read` | | 创建文档 | `doc create --name <标题> --content-file [--folder | --workspace ]` | 原生写入管道自动分片;取 `nodeId` 后 `doc read`,缺链接再 `doc info` | +| 显式块工作流 | 按用户原顺序执行 `create → block list → block insert/update/...` | 用户点名的 list/insert/append/update 是可观察要求,不得把后续动作折叠进一次 create;“插入/追加一个标题或列表块”走 block insert | | 末尾补短文本 | `+doc-append --doc --text <内容>` | 该 Shortcut 为 write/user_required;确认后执行并 `doc read` 核对 | | 改写正文 | `doc read --content-format jsonml` → `block update` 或 `doc update --content-format jsonml --mode overwrite` | 单块优先块级编辑;整篇 overwrite 先预览/确认,Markdown overwrite 不保富结构 | | 评论与回复 | `+comment-list --node ` → `+comment-create` / `+comment-reply` | `commentKey` 来自真实结果;写 Shortcut 先确认;划词评论走 atomic `comment create-inline` | -| 导入 / 导出 | `doc import --file ...` / `doc export --node --export-format --output ` | 一体化命令优先;仅超时/中断后用 `import get` / `export get` | +| 导入 / 导出 | `doc import --file ...` / `doc export --node --export-format --output ` | Word/Excel 等本地文件要求“在线编辑/转在线文档”必须 import;drive upload 只保留普通文件。仅超时/中断后用 `import get` / `export get` | | 版本操作 | `+version-list --node ` → `+version-save` / `+version-revert --version ` | save/revert 先确认;revert 版本号必须来自 list,完成后回读 | | 模板创建 | `+template-list` / `+template-search --query <词>` → atomic `template apply --template-id ` | templateId 来自真实列表;要复刻已有文档形态时用 drive copy + 副本块级更新 | | 分享链接给某人 | `+share-doc --to <姓名> --url [--note <附言>]` | 会真实发消息,确认后执行;同名人员必须消歧,不改变文档权限 | ## 写入与验证边界 +- `--name` 是文档外壳标题,但不能覆盖用户显式要求的正文 H1。用户说“正文写 `# ...` / 先起一级标题 / 插入一级标题”时,必须原样创建正文 H1;只有用户未要求正文 H1 时才默认从 H2 开始以避免重复。 +- 用户显式列出的操作是验收步骤:create 只能承载明确要求的初始内容;后续 `list`、`insert`、`append`、`update` 必须逐项真实调用。若要求“有序列表块”,必须写入 JSONML `p.list.isOrdered=true`(或等价原生列表块),普通 Markdown/普通段落不算完成。 - 创建只用 `--name`;内容只用 `--content` / `--content-file`。长、多行、表格或特殊字符必须用临时 UTF-8 文件和 `--content-file`。 - 原生 Markdown 写入管道在内容超过 10,000 个 Unicode 字符时自动按结构分片;不要在 Skill 或脚本中预先复制分片循环。仅在 `CONTENT_TRUNCATED`、中断或回读缺失时按 [04-document.md](references/04-document.md) 恢复。 - `doc update --mode append` 不清空原文;`--mode overwrite` 会清空后重写,先 `--dry-run`,得到确认后才加 `--yes`。 - 已有 callout、分栏、样式、@人、图片或附件时,先读 JSONML;局部改动优先 `block update`,不要用 Markdown 整篇重写。 - `block insert` 默认追加;只有明确相对位置时才传真实 `--ref-block` / `--parent-block`。`block delete` 和评论删除必须确认。 - 写后按对象验证:正文用 `doc read`,块/附件用 `doc block list`,元信息/链接用 `doc info`,版本用 `version list`。 +- 工具退出码 0、`success=true`、空对象或 `null` 都不能单独证明成功。每个写步骤必须同时有非空业务结果和针对目标字段的回查;例如 comment update 返回 `null` 且 list 仍是旧内容时,该步骤失败,最终必须报告“部分完成/更新未生效”,不得以“全部完成”开头。 +- 汇总和改写只能重组用户给出的事实,不得增强确定性或新增任务:“验证 12 条用例”不能写成“12 条全部通过”,“整理问题清单”不能扩写成“输出根因分析”。数字、状态、结论和承诺逐项保持原义。 ## 低频 atomic 路由 @@ -90,6 +96,7 @@ dws doc - 路径或参数错误:按既定顺序查 leaf Schema、再查 leaf Help,校正一次;不要连续尝试近似参数。 - 始终从实际输出重新提取 `nodeId`、`blockId`、`commentKey`、`jobId` 或 `taskId`。 +- 新建资源已返回 ID 后,把该 ID 绑定到同一请求的后续步骤;除非用户明确指向另一个历史资源,否则不得搜索同名项覆盖绑定。 - 部分写入或回读缺失:保留已创建的 nodeId,报告已完成范围与缺失位置;先读回,再只补缺失内容,禁止无条件重新创建副本。 - 权限不足、候选未消歧、目标类型不符、没有可推进的任务 ID 或 Schema/Help 冲突时停止并报告。 diff --git a/skills/multi/dingtalk-doc/references/04-document.md b/skills/multi/dingtalk-doc/references/04-document.md index 306697c0..f43bb056 100644 --- a/skills/multi/dingtalk-doc/references/04-document.md +++ b/skills/multi/dingtalk-doc/references/04-document.md @@ -57,3 +57,10 @@ dws doc read --node # 校验关键标题、段落首句、表格、@ ``` **禁止**在未回读的情况下向用户报告「已完成」。 + +## 显式工作流与事实保真 + +- 用户点名的 `create → list → insert/append/update` 是可观察命令链,必须保持顺序逐项执行;create 只承载明确的初始正文。有序列表块必须验证回读结构中的 `list.isOrdered=true`。 +- 新建资源返回 ID 后,同一请求的指代默认绑定该新资源;禁止搜索同名旧资源替换绑定。 +- 汇总用户材料时保留证据强度:验证数量不等于通过数量,计划整理问题不等于承诺根因分析。不得为“更专业”而补造结论、状态或任务。 +- 任一步骤返回 `null`/空结果或回查不一致时,该步骤未完成;最终按步骤报告成功与失败,不能用其他成功步骤把整体描述成“全部完成”。 diff --git a/skills/multi/dingtalk-doc/references/doc/doc-block.md b/skills/multi/dingtalk-doc/references/doc/doc-block.md index 456650a5..0f7a31b2 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-block.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-block.md @@ -10,6 +10,8 @@ > **改写已有文档优先 JSONML**:保真度最高、callout / 分栏 / 表格 / @人 / 附件 / 颜色 / 嵌套都能 1:1 round-trip;写入端有 validator 兜底。详见 [`./style/doc-update-workflow.md` §1.3 编辑形态优先级](./style/doc-update-workflow.md)。 +> **显式块操作不可折叠**:用户说“先 create,再 list/insert/update/append”时按原顺序真实调用;不能因为最终正文相似,就把后续块操作合并进 create 或一次 Markdown 写入。 + --- ## doc block list(查询块元素) @@ -173,7 +175,8 @@ dws doc block delete --node DOC_ID --block-id UUID - **块类型**:paragraph、heading、blockquote、callout、columns、orderedList、unorderedList、table、sheet、attachment、slot。 - **快捷 vs --element**:`block insert` 优先使用 `--text` 或 `--heading` 快捷方式;复杂块类型(table、callout、columns 等)使用 `--element` JSON 或 `--content-format jsonml`。 -- **简单内容追加**:建议用 [`./doc-update.md`](./doc-update.md) `--mode append`,不必走 block insert。 +- **有序列表块**:用户明确要求 ordered list / 有序列表块时,必须用 JSONML `p` 节点的 `list.isOrdered=true`(同一 `listId`;仅首项设 `start:1`)或等价原生 orderedList element;带 `1.` 前缀的普通段落、普通 Markdown 或一次 create 不满足要求。 +- **简单内容追加**:用户只说追加纯文本且不强调块操作时可用 [`./doc-update.md`](./doc-update.md) `--mode append`;用户明确说 block insert / 插入段落 / 插入标题 / 插入列表块时必须走 block insert。 - **JSONML validator**(写入端默认行为): - 裸字符串、缺 uuid 等结构错误会被 validator 抦下并返回带 path 的错误(如 `$[2][2]: paragraph child must be span wrapper, got raw string.`)。 - `--fix-jsonml` 开启 JSON 语法修复,推荐 agent 调用。 @@ -241,6 +244,12 @@ dws doc block list --node --content-format jsonml --block-id dws doc block insert --node --content-format jsonml --ref-block --where after \ --element '["p",{},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"新段落"]]]' +# 插入有序列表块(3 项共用 listId,仅首项有 start) +dws doc block insert --node --content-format jsonml \ + --element '["p",{"uuid":"ol1","list":{"listId":"actions","level":0,"isOrdered":true,"start":1}},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"第一项"]]]' +dws doc block insert --node --content-format jsonml \ + --element '["p",{"uuid":"ol2","list":{"listId":"actions","level":0,"isOrdered":true}},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"第二项"]]]' + # 插入 callout(colorBlocks) dws doc block insert --node --content-format jsonml --ref-block --where after \ --element '["container",{"uuid":"co1","subType":"colorBlocks","metadata":{"bgcolor":"#FDE2E0","border":"#F5C2C7"}},["p",{"uuid":"co1p1"},["span",{"data-type":"text"},["span",{"data-type":"leaf"},"高风险操作,先备份"]]]]' diff --git a/skills/multi/dingtalk-doc/references/doc/doc-comment.md b/skills/multi/dingtalk-doc/references/doc/doc-comment.md index 6bdc7eab..d90b7d08 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-comment.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-comment.md @@ -135,6 +135,7 @@ Flags: - `reply` 加 `--emoji` 时 `--content` 填表情名称(如 `比心`、`赞`),不是文字内容。 - `reply --emoji` 与群 mention 冲突;CLI 会在调用服务端前报错,不会静默忽略。 - `delete` 是不可逆操作;AI Agent 必须先让用户确认,再追加 `--yes`,避免 CLI 进入交互等待。 +- `comment create/reply/update/delete` 的退出码 0 不等于业务成功。响应为 `null`、空对象或缺少可核验字段时,立即执行 `comment list` 回查目标 `commentKey`。若 update 后正文仍是旧值,必须判定“更新未生效”;即使其他步骤成功或评论随后被删除,也只能报告部分完成,禁止写“全部完成”。 ## 上下文传递 diff --git a/skills/multi/dingtalk-doc/references/doc/doc-create.md b/skills/multi/dingtalk-doc/references/doc/doc-create.md index c07abd5d..01be5c34 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-create.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-create.md @@ -40,7 +40,7 @@ Flags: ## 关键说明 -- **`--name` 是 H1**:正文从 `##` 开始;正文内不要再写 `#` 一级标题(除非确需且已说明动机)。 +- **标题优先级**:`--name` 是文档外壳标题,默认可视作 H1;但它不能替代用户显式要求的正文一级标题。用户说“正文写 `# ...`”“正文先起个一级标题”时,必须在初始内容中保留该 `#` H1;用户未要求正文 H1 时,正文默认从 `##` 开始以避免重复。 - 不传 `--folder` 和 `--workspace` 时,默认创建在「我的文档」根目录。 - `--folder` 仅接受文档文件夹 `nodeId` / `dentryUuid` / alidocs 文件夹 URL;**禁止**传入 drive `dentryId`、`parentId`、`spaceId` 这类纯数字 ID。 - 输入方式选择见 [`./doc-update.md` §内容写入管道](./doc-update.md)(与 update 共用)。短文本字面量可 `--content`,多行/表格/特殊字符必须 `--content-file` 或 `--content -`。 @@ -54,6 +54,12 @@ Flags: | `docUrl` | 最终交付给用户的链接;缺失时用 [`./doc-info.md`](./doc-info.md) 补查 | | `chunksWritten` | 判断是否触发自动分片;> 1 时重点检查章节顺序 | +同一请求后续出现“这篇/刚才那篇/上次那篇”时,直接续用本次 create 返回的 `nodeId`;禁止先搜索同名文档再把后续操作指向旧节点。 + +## 显式操作序列 + +用户点名 `block list`、插入、追加、更新等后续动作时,必须按原顺序逐项执行。`doc create` 只写用户指定的初始内容,不能为了减少调用把后续标题、列表或段落提前塞进 create。例:`创建 → 查看块结构 → 末尾插入段落` 必须真实执行 create、block list、block insert 三步。 + ## 回读验收(必读) CLI **不会**自动回读校验。**每次创建后**都必须执行 `doc read --node ` 校验关键标题、段落首句、表格表头是否完整。详见 [`./style/doc-create-workflow.md` «回读验收»](./style/doc-create-workflow.md)。 diff --git a/skills/multi/dingtalk-doc/references/doc/doc-export.md b/skills/multi/dingtalk-doc/references/doc/doc-export.md index 319b2aee..6676d130 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-export.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-export.md @@ -51,6 +51,7 @@ Flags: ## 关键说明 +- 同一请求中刚执行 create/copy/import 并紧接着说“这篇/刚才那篇/上次那篇”时,`--node` 必须使用该写操作真实返回的新 `nodeId`;不得预先搜索同名文档,也不得用搜索结果中的旧节点替换它。 - `export` 是一体化命令,一条命令自动完成提交→轮询→下载,**无需手动编排轮询**。CLI 内部使用渐进式退避轮询(最多约 5 分钟)。 - `export` 超时或中断后,CLI 会输出 `jobId`,可用 `dws doc export get --job-id ` 手动查询任务状态。 - `export` 支持钉钉在线文档(alidocs,`contentType=ALIDOC`)导出为 `docx`、`markdown` 或 `pdf`,**在线表格导出请使用其他命令**。 diff --git a/skills/multi/dingtalk-doc/references/doc/doc-import.md b/skills/multi/dingtalk-doc/references/doc/doc-import.md index 7387fe48..aa30eb64 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-import.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-import.md @@ -6,6 +6,8 @@ > **支持的文件格式**:docx, doc, xlsx, xls, md, txt, xmind, mark > **文件大小限制**:20MB +> **在线编辑硬路由**:用户说“上传后在线编辑/大家直接在线改/转成钉钉文档”时必须使用 `doc import`。`drive upload` 只保留原始 `.docx/.xlsx/...` 普通文件,不能据此宣称已可在线编辑。若用户明确要同时保留原文件和在线版,才先 `drive upload`,再单独 `doc import`,并分别验证两个返回节点。 + --- ## doc import(一体化命令) @@ -63,6 +65,7 @@ Flags: ## 关键说明 - `import` 是一体化命令,一条命令自动完成创建会话→上传→确认→轮询,**无需手动编排**。CLI 内部使用渐进式退避轮询(最多约 5 分钟)。 +- 导入完成后必须用返回的 `documentUrl`/`nodeId` 执行 `drive info` 或 `doc info`,确认 `extension=adoc`(Word/文本)或对应在线类型,并确认目标 `folderId`;只有验证后才能说“可直接在线编辑”。 - `import` 超时或中断后,CLI 会输出 `taskId`,可用 `dws doc import get --task-id ` 手动查询任务状态。 - 支持的文件格式:docx, doc, xlsx, xls, md, txt, xmind, mark(共 8 种)。 - 文件大小限制:20MB。超过限制时 CLI 会直接报错,不会发起网络请求。 diff --git a/skills/multi/dingtalk-doc/references/doc/style/doc-create-workflow.md b/skills/multi/dingtalk-doc/references/doc/style/doc-create-workflow.md index e055629e..77440175 100644 --- a/skills/multi/dingtalk-doc/references/doc/style/doc-create-workflow.md +++ b/skills/multi/dingtalk-doc/references/doc/style/doc-create-workflow.md @@ -8,7 +8,7 @@ > **同时读取 [doc-style-guideline.md](./doc-style-guideline.md):** > - **§2.0 类型判断决策表** → 锁定文档类型(决策型 / 执行型 / 说明型 / 知识沉淀型)和骨架 -> - **§1 硬规则** → 全程生效(`--name` 已是 H1、不编造 URL、Markdown 草稿不写 callout 等) +> - **§1 硬规则** → 全程生效(用户显式正文 H1 优先、不编造 URL、Markdown 草稿不写 callout 等) ### 关键词速查(用户意图 → 起稿路径) @@ -274,7 +274,7 @@ callout 可通过 `"showstk": true, "sticker": "图标名"` 配置顶部贴纸 ``` - 根节点固定 `"root"`(不是 `"body"`) -- `--name` 已是 H1,JSONML 从 `h2` 开始 +- 用户未要求正文 H1 时,JSONML 从 `h2` 开始;用户明确要求“正文一级标题/插入一级标题”时必须构造 `h1` - 表格结构是 `table → tr → tc`(无 `th`/`td`) - 分栏是 `table` + `"sr": true`,`tc` 建议设 `fill` 背景色 - 有序列表:仅第一项设 `"start": 1`,后续项不设 `start`(系统自动递增) @@ -315,7 +315,7 @@ dws doc read --node --content-format jsonml --output /tmp/-readba - 只使用用户已提供或对话中已确认的正文素材。 - 如果正文素材不足,先补齐文档目标、受众、章节和缺口;不要在本文中临时扩展跨产品采集流程。 - **先按 [doc-style-guideline.md §2.0 类型判断决策表](./doc-style-guideline.md) 确定文档类型,再用对应类型的骨架样板(§2.1 决策型 / §2.2 执行型 / §2.3 说明型 / §2.4 知识沉淀型)**。不要套通用三段式。 -- **`--name` 已是 H1,正文从 `##` 开始**;正文内不要再写 `#` 一级标题(除非确实需要正文内再造一级 H1 并说明动机)。 +- **`--name` 是外壳标题,不覆盖显式正文 H1**:用户未要求正文一级标题时从 `##` 开始;用户明确给出 `# ...` 或要求“先起一级标题”时,正文必须保留该 H1。 - 摘要、bullet、引用块、callout 等元素的使用边界以 style-guideline §3-§7 为准。 - 同类信息保持一致:风险、状态、行动项各用一种元素 + 一种视觉语义(style-guideline §1.2 / §5)。 - 临时文件必须保留真实换行,不能把换行写成字面量 `\n`。 diff --git a/skills/multi/dingtalk-doc/references/doc/style/doc-style-guideline.md b/skills/multi/dingtalk-doc/references/doc/style/doc-style-guideline.md index 1e00cad5..e1162376 100644 --- a/skills/multi/dingtalk-doc/references/doc/style/doc-style-guideline.md +++ b/skills/multi/dingtalk-doc/references/doc/style/doc-style-guideline.md @@ -25,7 +25,7 @@ ## 一、硬规则 -1. **`--name` 是 H1**:正文从 `##` 开始;正文内不写 `#`(除非确需正文内再造一级 H1 并说明动机) +1. **用户显式正文 H1 优先**:`--name` 是文档外壳标题;用户未要求正文一级标题时从 `##` 开始。用户明确说“正文写 `# ...` / 先起一级标题 / 插入一级标题”时必须保留或插入真实 H1,不得用 `--name` 代替 2. **同类信息同表达**:风险、状态、行动项、证据,每类只用一种元素 + 一种视觉语义(见 §5) 3. **Markdown 草稿阶段只用稳定元素**:标题、段落、列表、checklist、表格、代码块;callout / 分栏 / 附件 / 复杂嵌套留到创建后用 `doc block insert` / `doc media insert` 精修 4. **引用块只用于原文**:用户原话、会议摘录、外部材料原文;不许包装作者自己的结论 @@ -209,7 +209,7 @@ ### 4.1 标题与段落 -- 正文从 `##` 开始(H1 已被 `--name` 占用) +- 用户未要求正文 H1 时从 `##` 开始;用户明确要求正文 H1 时按原文使用 `#` 或 heading level 1 - 标题层级 ≤ 4 层(§7) - 单段过长先拆段,再考虑换元素 @@ -217,6 +217,7 @@ - 普通列表:并列要点 - 有序列表:顺序步骤 +- 用户明确要求“有序列表块”时必须使用真实列表结构;JSONML 为带 `list.isOrdered=true` 的多个 `p` 节点,不能只写带数字前缀的普通段落或以整篇 Markdown 代替显式 block insert - checklist:待办状态(含 `- [ ]` / `- [x]`) 列表项里开始出现"负责人 / 截止时间 / 状态"这类字段时,改用表格。 diff --git a/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py b/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py index a306b0e5..4f2d9f29 100644 --- a/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py +++ b/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py @@ -60,6 +60,8 @@ def run_dws(args: Sequence[str], dry_run: bool = False) -> Any: f"dws 命令失败:{detail or f'退出码 {result.returncode}'}" ) data = decode_json_output(result.stdout) + if data is None or data == {}: + raise ScriptError("dws 返回空业务结果,无法确认操作成功") if isinstance(data, dict) and data.get("success") is False: detail = data.get("errorMsg") or data.get("message") or "未知错误" raise ScriptError(f"dws 业务调用失败:{detail}") @@ -145,12 +147,14 @@ def run(argv: Optional[Sequence[str]] = None) -> int: ["doc", "info", "--node", node_id, "--format", "json"], dry_run=args.dry_run, ) - run_dws( + readback = run_dws( ["doc", "read", "--node", node_id, "--format", "json"], dry_run=args.dry_run, ) if args.dry_run: return 0 + if not first_value(readback, ("markdown", "jsonml", "content")): + raise ScriptError("文档回读未返回正文,无法确认写入成功") summary = { "success": True, diff --git a/test/scripts/doc_skill_scripts_test.py b/test/scripts/doc_skill_scripts_test.py index 7a68b873..bfdf3026 100644 --- a/test/scripts/doc_skill_scripts_test.py +++ b/test/scripts/doc_skill_scripts_test.py @@ -14,6 +14,8 @@ from unittest import mock ROOT = Path(__file__).resolve().parents[2] SKILL_ROOT = ROOT / "skills" / "multi" / "dingtalk-doc" SCRIPT_PATH = SKILL_ROOT / "scripts" / "doc_create_and_write.py" +MONO_DOC_ROOT = ROOT / "skills" / "mono" / "references" / "products" / "doc" +MONO_SCRIPT_PATH = ROOT / "skills" / "mono" / "scripts" / "doc_create_and_write.py" def load_script(): @@ -69,6 +71,86 @@ class DocSkillAlignmentTest(unittest.TestCase): self.assertNotIn("超过 200KB", combined) self.assertNotIn("doc get", combined) + def test_workflow_identity_and_fidelity_rules_are_explicit(self): + skill = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8") + create_refs = "\n".join( + path.read_text(encoding="utf-8") + for path in [ + SKILL_ROOT / "references" / "doc" / "doc-create.md", + MONO_DOC_ROOT / "doc-create.md", + ] + ) + block_refs = "\n".join( + path.read_text(encoding="utf-8") + for path in [ + SKILL_ROOT / "references" / "doc" / "doc-block.md", + MONO_DOC_ROOT / "doc-block.md", + ] + ) + import_refs = "\n".join( + path.read_text(encoding="utf-8") + for path in [ + SKILL_ROOT / "references" / "doc" / "doc-import.md", + MONO_DOC_ROOT / "doc-import.md", + ] + ) + comment_refs = "\n".join( + path.read_text(encoding="utf-8") + for path in [ + SKILL_ROOT / "references" / "doc" / "doc-comment.md", + MONO_DOC_ROOT / "doc-comment.md", + ] + ) + + self.assertIn("不能覆盖用户显式要求的正文 H1", skill) + self.assertIn("禁止先搜索同名文档", create_refs) + self.assertIn("显式块操作不可折叠", block_refs) + self.assertIn("list.isOrdered=true", block_refs) + self.assertIn("在线编辑硬路由", import_refs) + self.assertIn("update 后正文仍是旧值", comment_refs) + self.assertIn("验证 12 条用例", skill) + self.assertIn("部分完成/更新未生效", skill) + + def test_schema_selection_preserves_doc_drive_boundaries(self): + doc = json.loads( + ( + ROOT / "internal" / "cli" / "schema_hints" / "selection" / "doc.json" + ).read_text(encoding="utf-8") + )["tools"] + drive = json.loads( + ( + ROOT + / "internal" + / "cli" + / "schema_hints" + / "selection" + / "drive.json" + ).read_text(encoding="utf-8") + )["tools"] + + self.assertIn( + "正文 H1", + " ".join(doc["doc.create_document"]["use_when"]), + ) + self.assertIn( + "list.isOrdered=true", + " ".join(doc["doc.insert_document_block"]["use_when"]), + ) + self.assertIn( + "null/空对象", + " ".join(doc["doc.update_comment"]["avoid_when"]), + ) + self.assertIn( + "dws doc import", + " ".join(drive["drive.upload"]["avoid_when"]), + ) + + def test_mono_and_multi_wrappers_stay_aligned(self): + self.assertEqual( + SCRIPT_PATH.read_text(encoding="utf-8"), + MONO_SCRIPT_PATH.read_text(encoding="utf-8"), + ) + class DocCreateAndWriteTest(unittest.TestCase): def setUp(self): @@ -121,6 +203,16 @@ class DocCreateAndWriteTest(unittest.TestCase): with self.assertRaisesRegex(self.module.ScriptError, "denied"): self.module.run_dws(["doc", "create"]) + with mock.patch.object( + self.module.subprocess, + "run", + return_value=subprocess.CompletedProcess( + ["dws"], 0, stdout="null", stderr="" + ), + ): + with self.assertRaisesRegex(self.module.ScriptError, "空业务结果"): + self.module.run_dws(["doc", "create"]) + def test_wrapper_uses_create_then_info_and_read_without_manual_update(self): calls = [] @@ -144,6 +236,18 @@ class DocCreateAndWriteTest(unittest.TestCase): self.assertEqual("doc-1", summary["nodeId"]) self.assertTrue(summary["verified"]) + def test_wrapper_rejects_empty_readback(self): + def fake_run(args, dry_run=False): + if args[:2] == ["doc", "create"]: + return {"success": True, "nodeId": "doc-1"} + if args[:2] == ["doc", "info"]: + return {"success": True, "docUrl": "https://example.test/doc-1"} + return {"success": True, "markdown": ""} + + with mock.patch.object(self.module, "run_dws", side_effect=fake_run): + with self.assertRaisesRegex(self.module.ScriptError, "回读未返回正文"): + self.module.run(["--name", "周报", "--content", "hello"]) + def test_dry_run_shows_create_and_verification_commands(self): stdout = io.StringIO() with contextlib.redirect_stdout(stdout):