关于 cawplan-product-report
CawPlan Product Report 是基于 CawPlan 工单和活动生成产品、版本、团队及成员报告的技能。它按请求类型路由查询流程,并强调准确匹配记录及可核查的工单分类。
主要功能
- 01产品与版本活动报告
- 02汇总团队工单变更
- 03按标签分类工单
- 04统计状态、经办人和优先级
- 05报告重新打开事件
- 06精确匹配产品与工单标题
适用场景
- 01查看产品版本的未关闭工单
- 02跨版本查找特定类别工单
- 03汇总产品团队的活动
- 04按状态或经办人统计工单
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cawcut/ skill-cawplan --skill cawplan-product-report安装后在 Claude Code 中输入/cawplan-product-report确认已加载。
附带文件references/QUERY_RESILIENCE.md
详细介绍
CawPlan 产品报告
引导设置
cawplan skill check
入口路由
| 输入 | 流程 |
|---|---|
| 按类别和可选关键词查询整个产品的未完成/未关闭工单(例如“VN iOS Collage bugs”) | A1 — 整个产品的标签筛选工单 |
| 查询产品当前版本或指定版本中的未关闭/未完成工单 | A0 — 版本未关闭工单 |
| 指定产品(以及可选的版本) | A — 产品报告 |
| 一个 Team/产品线(“Team A”、小组/产品线名称,而非产品名称) | B — Team 报告 |
| 产品 UX 成员的 UX/设计完成情况 | 使用 cawplan-ux-tracking 工作流 D;它统计由产品配置的设计师执行的 ux → READY 事件,而非报告人或受派人执行的事件。 |
| 产品 QA 成员的工单验证/验收状态 | D — QA 验证活动;统计由产品配置的 QA 成员执行的状态变更事件,而非当前受派人执行的事件。 |
| 指定成员,即调用者以外的其他人(“Alex 在……方面做得怎么样”) | C — 成员报告 |
| 按状态、受派人、优先级、标签或 UX 统计产品、版本或 Team 中的工单数(“当前版本各状态多少条”“每个 Assignee 多少条”) | 每个维度调用一次,并使用 --product_ids 或 --version_ids 限定范围:cawplan tickets stats --version_ids <version_id> --start_date 2000-01-01 --end_date <today> --group_by status(然后使用单数形式的 --group_by assignee)。必须指定日期范围。参见 references/QUERY_RESILIENCE.md §1。不要通过翻页查询 tickets search 来计数。 |
| 在一段时间内,产品、版本、Team 或成员范围内重新打开的工单(“哪些被 reopen 了”) | 使用 references/QUERY_RESILIENCE.md(“Reopens”)中的定义和命令,并通过 --product_ids、--version_ids、--product_line_ids 或成员的候选 --unique_ids 限定范围。报告每个重新打开事件(工单、之前的状态 → 新状态、时间)。不要仅限于状态名称为“Reopen”的工单。 |
如果不确定某个名称是产品还是 Team,请分别查询两者(products list --search、product-lines list);如果其中一个或两者都存在歧义,请向用户确认。用户提供的 Team 或产品名称必须与可访问记录完全匹配(忽略大小写、去除首尾空格后),或唯一匹配短名称/令牌前缀。如果无法唯一匹配,请列出可用的或搜索返回的候选项,并询问用户指的是哪个 Team/产品;绝不要替换为名称相似的产品或 Team。如果用户询问的是自己的任务完成情况(“我的任务”),应使用 cawplan-my-work,而非此技能。
通用工单规则
标签是分类的唯一可信来源
不要使用旧版工单 type、--type 搜索选项或返回的 .type 字段来判断工单属于错误、功能或其他类别。应根据已确认产品可见的标签确定分类,并使用 --label_ids 筛选。为保持兼容性,API 响应中可能仍会出现旧字段;进行类别判断时请忽略它。
工单标题须忠实保留
工单响应的 description 字段是规范标题。显示工单标题时,必须逐字照录:不要翻译、概括、缩短、改写、规范化标点或空格、删除前缀或省略括号中的文本。如果有必要补充说明或摘要,请放在单独字段中。为保留标题的相同显示效果而进行 Markdown 转义(例如转义表格竖线)是允许的。
工作流 A0 — 当前版本未关闭工单
对于“查看 VN Cloud 当前 Version 的 Open Tickets”或“列出 Product X 1.2.3 的未关闭工单”之类的请求,请使用此工作流。每次查询前,都必须先应用工作流 A 的必需产品访问权限检查。不得根据相似名称、别名、之前的查询或其他产品的当前版本推断产品。
-
使用以下命令解析请求中的产品:
cawplan products list --search <product-name-word-or-product_id>将搜索文本作为一个不带引号的标记传入(使用
--search CawPlan,绝不要使用--search "CawPlan"):托管 Agent 会拒绝带引号的值。对于包含空格的名称,请搜索一个有辨识度的词,并在结果中匹配完整名称。 仅在名称完全匹配且可访问,或唯一的简称/令牌前缀匹配时继续。如果没有候选项匹配,请报告:“没有与<input>匹配的可访问 Product;它可能不存在、名称不同,或你可能没有权限。”不要查询版本或工单。如果 API 明确返回访问被拒绝错误,请报告NO_PERMISSION;否则,不要断言一定是权限不足。 -
解析版本。对于“当前 Version”,使用匹配产品的
inprogress_version_id和inprogress_version_name;如果其中任一项缺失,请报告该产品没有当前进行中的版本。对于指定版本,请使用cawplan versions list <product_id>,并要求版本名称完全匹配。绝不要借用其他产品的版本。 -
获取该版本中的所有工单,分页直至达到
total:cawplan tickets search --version_ids <version_id> --start_date 2000-01-01 --end_date <today> --page_size 100 --page_num 1仅当工单内联字段
status_display.category既不是COMPLETE也不是CANCELED时,才将其视为未关闭。即使提供了--excluded_status_categories COMPLETE,CANCELED筛选条件,也必须在客户端进行筛选;不能仅依赖服务端排除作为唯一保障。 -
报告解析出的 Product 和 Version、未关闭工单总数,以及状态/优先级明细。对于每张列出的工单,显示展示 ID、标签、优先级、状态以及原样的
description标题。如果结果过多,不适合在聊天回复中完整呈现,请先提供数量和明细,再询问是否需要按优先级/状态筛选或导出;不得暗中替换为其他产品,也不得将不完整列表报告为完整列表。
工作流 A1 — 按标签筛选产品范围内的工单
对于“列出 VN iOS 的剩余 Collage Bug”等请求,请使用此工作流。除非用户明确缩小范围,否则查询范围会有意涵盖进行中的版本和 Backlog。
-
确认请求中的产品,并完成工作流 A 的必需产品访问权限检查。保留已确认的
product_id;不要根据名称相似来推断产品。 -
获取该产品可见的完整标签目录:
cawplan labels list --product_id <product_id> --page_size 200 --page_num 1翻页直至
total。此产品范围内的目录包含通过其团队/产品线适用的标签,以及任何工作区级标签。只能从实际返回的记录中选择;绝不要编造标签名称或 ID,也不要用未限定范围的工作区级目录代替。 -
将用户请求的类别与返回的目录进行匹配。比较时统一大小写、空格、连字符和下划线,但保留返回的确切标签 ID 和名称:
- 如果用户表达的是 Bug/缺陷意图,那么所有
behavior为BUGFIX的返回标签都是强匹配。 - 如果标签名称本身或其中明确的词语/短语包含
bug、bugs、bugfix、bug fix、defect、defects、regression或regressions,则是强名称信号;但不能将debug之类任意子字符串视为匹配。 fix、fixing、hotfix、issue、crash、incident和blocker是依赖上下文的候选项。仅当返回的目录和用户措辞能清楚表明其类别含义时才选择;不要盲目地将Fixing之类的工作流/状态标签视为 Bug 分类。Feature、Enhancement、Blocked和优先级标签并非 Bug 标签,即便它们可能出现在 Bug 工单上。- 对于非 Bug 类别,采用相同的语义规则:只选择返回目录中能清楚表达用户所请求类别的标签。
- 如果有多个标签符合安全的语义匹配条件,则全部选中。搜索会在
label_ids中按 OR 处理这些标签,再与其他筛选条件按 AND 处理。 - 如果没有任何返回标签符合安全匹配条件,则展示最接近的候选标签并请用户选择。不要回退到旧版
type。
- 如果用户表达的是 Bug/缺陷意图,那么所有
-
查询所有匹配的工单。使用步骤 3 中的 ID;仅当用户另行提供了标题/文本关键词(例如
Collage)时才添加--search:cawplan tickets search \ --product_ids <product_id> \ --label_ids <comma-separated-selected-label-ids> \ --search <optional-keyword> \ --start_date 2000-01-01 \ --end_date <today> \ --excluded_status_categories COMPLETE,CANCELED \ --page_size 100 \ --page_num 1没有单独关键词时省略
--search。当page_num * page_size < total时继续翻页。--search会跨多个工单字段进行全文匹配,而不是结构化的模块筛选。因此,像Photo Edit ... Collage这样的工单即便不属于 Collage 模块,也可能匹配Collage。不要将关键词搜索结果描述为严格的模块归属。如果用户要求模块范围纯粹的列表,而 API 未提供专用的模块筛选器,请说明此限制。不要把模块标签与 Bug 标签一起添加到同一--label_ids参数中作为变通方法:label_ids中的值按 OR 处理,因此会返回bug OR module,而不是bug AND module。 -
仅当每条结果内联的
status_display.category既不是COMPLETE也不是CANCELED时,才在客户端独立归类为未关闭;TESTING仍视为未关闭。即使服务器已提供排除条件,这项客户端检查仍是必需的。 -
确保分类结果可核查。在结果表格之前,列出确切选中的标签(名称、ID 及各自的匹配原因;如有
behavior=BUGFIX,也要注明)。随后报告解析出的 Product、未关闭工单总数、状态/优先级/版本分布,以及每条工单的展示 ID、标签、版本或 Backlog、优先级、状态和原样引用的description标题。绝不要展示改写后的标题,也不要将不完整的分页结果说成完整列表。
工作流 A — 产品报告
必需的产品访问权限检查
在查询任何产品、版本或工单范围的数据之前,请确认请求的产品出现在调用方的 products list 响应中。即使调用方直接提供了产品 ID,或该 ID 保留自先前的上下文,也必须执行此检查。
cawplan products list --search <product-name-word-or-product_id>
只有在通过精确匹配或唯一的简称匹配确定一个目标产品(product_id / unique_id)后,才能继续。如果用户指定的产品没有唯一的可访问匹配项,请停止操作,并让用户从候选项中确认目标产品;不要查询产品、版本、活动或工单。只有在 API 明确报告访问被拒绝时,才使用 NO_PERMISSION。切勿将无法访问或未能确认的产品报告为成功的空结果(例如,Open Tickets: 0)。
-
将产品名称解析为
product_id,并完成必要的产品访问权限检查:cawplan products list --search <product-name-word>如果没有精确匹配或唯一的简称匹配,请列出候选项(名称 +
product_id),并询问用户想查询哪个产品;不要猜测。此技能中的所有产品范围工作流都必须按此方式解析产品。 -
如果用户指定了版本范围,则将版本名称解析为
version_id:cawplan versions list <product_id> -
获取产品报告:
cawplan product-activity get \ --product_id <product_id> \ --start YYYY-MM-DD \ --end YYYY-MM-DD # Scoped to a specific version: cawplan product-activity get \ --product_id <product_id> \ --version_id <version_id> \ --start YYYY-MM-DD \ --end YYYY-MM-DD -
报告特定版本时,补充版本进度信息:
cawplan versions get <product_id> <version_id>这会提供
progress.complete_percent、risk、risk_reason和target_release。
工作流 B — 团队报告
没有团队范围的活动端点 — product-activity get 仅接受单个 --product_id。因此,请从团队中每个产品的工单变更构建报告。
-
将团队名称解析为
product_line_id。product-lines list不支持按名称筛选,因此请遍历所有分页,并在客户端按名称匹配:cawplan product-lines list --page_size 100如果没有名称匹配项,请询问正确的名称。如果匹配项不止一个,请列出候选项(名称 +
product_line_id,以及响应中包含的其他任何区分字段),并请用户选择;不要猜测。 -
获取整个团队的工单变更 — 这是报告所依据的工单变更数据:
cawplan tickets search --product_line_ids <product_line_id> --start_date 2000-01-01 --end_date <today> --updated_start_date <window_start> --updated_end_date <today> --page_size 100 --page_num 1- 报告时间范围应使用
--updated_start_date/--updated_end_date,而不是--start_date/--end_date— 后者筛选的是工单创建时间,而不是最后变更时间(参见references/CAWPLAN_OPEN_API.md),单独使用会漏掉较早创建、但在时间范围内实际已完成或取得进展的工单,从而悄悄低估“发生了哪些变化”。仍必须传入--start_date/--end_date(端点要求提供 created_at 时间范围或--time_range),所以应将其设为最大范围(2000-01-01至今天,与cawplan-ux-tracking使用的变通方法相同),避免它本身缩小结果范围 — 实际筛选由--updated_start_date/--updated_end_date完成。 - 传入
--updated_end_date <today>(实际的“今天”),而不是报告时间范围的结束日期 —updated_at会因任何字段变更而刷新,不仅仅是完成。因此,某个工单若在时间范围内完成,但之后又发生了无关编辑(版本转移、优先级调整、评论),其updated_at就会被推到时间范围结束日期之后;若将--updated_end_date截止到该日期,工单便会被悄悄排除(参见references/CAWPLAN_OPEN_API.md中updated_at并非“完成时间”的说明)。将结束边界放宽到今天,得到的是候选集,而非最终答案 — 下文第 2a 步会根据当前处于已完成/已取消状态的工单的实际完成时间,将范围重新缩小。创建时间位于[window_start, today]内的工单仍会被捕获(其updated_at初始值与created_at相同),因此结果仍是旧版仅按 created_at 筛选方式的严格超集。 - 对于“最近 N 天”这类请求,应在客户端计算
--updated_start_date(今天减去 N 天)—time_range只适用于 created_at 日期对,不适用于 updated_at 日期对。 - 响应是一个
CommonPageResp(data、page_num、page_size、total)— 按page_num * page_size < total的条件翻页;针对这一相同结构,cawplan-my-work/cawplan-ux-tracking也采用相同规则。在先检查total之前,不要因为某一页恰好已满就停止。 2a. 将候选范围缩小到报告时间窗口内实际发生状态变化的条目 —updated_at只是宽泛的候选筛选条件:任何编辑都会刷新此字段,包括某个子工单变更后重新计算父工单。 它绝不能作为此工单状态发生变化的证据。 - 通过一次批量调用获取整个团队的实际状态变更(时间窗口最长为 90 天;
更长的时间范围需拆分):
每条返回的事件都是窗口内发生的状态变更,包含cawplan tickets changes --product_line_ids <product_line_id> --fields status --start_date <window_start> --end_date <window_end>at、old→new和new_category。只有至少有一条事件的工单才予以保留。不能仅因工单的updated_at在窗口内就保留该工单。应根据事件的new_category(COMPLETE/CANCELED) 判断是否已终结,而不是硬编码DONE。仅用于计数时,--group_by new_category(或ticket) 可在服务端返回计数。 - 在摘要中每个工单只计数一次,并保留其窗口内最新事件作为展示的依据。状态未变更的父工单
不会有事件,因此应予以排除,即使子工单的变更刷新了父工单的
updated_at也不例外。响应中的tickets映射包含输出所需的展示 ID、标题、优先级、标签和版本。 - 如果结果为
truncated,请使用--cursor继续获取,或在报告前拆分时间窗口。 - 备用方案(仅当
tickets changes不可用时,参见references/QUERY_RESILIENCE.md):对步骤 2 中的每个候选项,调用cawplan tickets history <product_id> <version_id> <ticket_id>,仅当某条UPDATED记录的changed_fields.status(新的状态键字符串,或包含old和new的对象)的created_at位于[window_start, window_end]内时,才保留该工单;绝不能将CREATED视为状态变更。解析产品线的状态定义,根据类别对新状态进行分类。说明使用了较慢的 路径;如果无法检查所有候选项,则报告部分结果。
- 报告时间范围应使用
-
可选:解析团队由哪些产品构成(仅在用户要求按产品细分时):
cawplan products list --product_line_id <product_line_id>
工作流 D — QA 验证活动
对于“汇总 CawCut Cloud 的 QA Team 本周的 Ticket 验收情况”或
“汇总此产品的 QA Ticket 验证情况”等请求,请使用此工作流。此处的 QA Team 指产品已配置的 members.qas 名单,而非 CawPlan 产品线。如果未指定产品,请询问要汇总哪个产品的 QA 成员情况。此工作流统计的是 QA 活动:在请求的时间段内由 QA 成员实际执行的 Ticket 状态变更。不得使用当前 Assignee、Reporter 或 Ticket 当前状态来推断 QA 工作。
-
确定产品,并完成工作流 A 要求的产品访问权限检查:
cawplan products list --search <product-name-word-or-product_id>读取匹配产品的
members.qas[]名单,并收集其中的user_id值和显示名称。如果没有 QA 成员,请报告该产品未配置 QA 名单并停止。成员资格以产品为范围;请使用该产品返回的名单,而非在整个工作区进行关键字搜索。如果未指定日期范围,默认使用本周,并注明所采用的起止日期(含首尾)。 -
使用一次批量调用,获取该 QA 名单成员在时间窗口内执行的所有状态变更(窗口最长为 90 天;更长的范围需拆分):
cawplan tickets changes --product_ids <product_id> --fields status --actor_ids <qa_user_ids_csv> --start_date <window_start> --end_date <window_end>返回的每个事件都是名单成员在时间窗口内执行的一次状态变更。不要统计
CREATED、TRANSFERRED、任意updated_at、非 QA 操作者执行的状态变更,也不要仅因 Ticket 当前分配给 QA 就将其计入。按 QA 成员统计时,--group_by actor,new_status_category会在服务端返回分组结果。如果结果为truncated,请使用--cursor继续获取,或拆分时间窗口。 -
回退方案(仅当
tickets changes不可用时使用,参见references/QUERY_RESILIENCE.md): 完全按照工作流 B 第 2 步构建候选集,包括分页:cawplan tickets search --product_ids <product_id> --start_date 2000-01-01 --end_date <today> --updated_start_date <window_start> --updated_end_date <today> --page_size 100 --page_num 1(
updated_at仅用于识别历史记录可能相关的 Ticket;其结束边界必须是实际的今天。)对每个候选项,调用cawplan tickets history <product_id> <version_id> <ticket_id>,并保留符合以下条件的所有UPDATED条目:存在changed_fields.status(通常为{old, new};若旧版格式为字符串,则将其视为新状态),created_at位于[window_start, window_end]内,且user_id属于members.qas名单。请说明使用了较慢的方式;如果未能检查所有候选项,请报告部分结果。 -
将每条保留的历史记录视为一项 QA 活动——不要按 Ticket 去重。一个 Ticket 在一周内可能会依次经历 QA Testing、Done、Reopen 和 Close;每次状态变更都能提供有用的验证证据。将活动归属给事件的
actor(或回退方案中历史记录的user_id/user_display_name),即执行变更的 QA 成员。不要根据 Ticket 的 Reporter 或 Assignee 推断该成员。如果条目没有 actor,且无法与产品 QA 名单中的成员匹配,则排除该条目;只有在有助于解释排除原因时,才单独将其标记为未分配/集成事件。 -
如需按类别细分,请使用各事件的
new_category;仅在回退方案中解析产品线的状态定义。显示实际状态变更(old → new),并在可用时显示新状态类别。不要将DONE、REOPEN、CLOSE或QA Testing硬编码为状态;自定义状态键和类别也属于有效的 QA 活动。
工作流 C — 成员报告
采用与工作流 B 相同的工单变更方法,但范围限定为一个人,而不是整条产品线。
-
将成员解析为
user_id:cawplan users query --email <email> # if the user gave an email cawplan users query --keyword <name-word> # if the user gave a name如果关键词查询返回多个人员,请列出他们(姓名 + 邮箱),并询问用户要选哪一位——不要猜测。
-
获取该成员在此期间的工单变更:
cawplan tickets search --assignees <user_id> --start_date 2000-01-01 --end_date <today> --updated_start_date <window_start> --updated_end_date <today> --page_size 100 --page_num 1如果用户还指定了产品/版本范围,添加
--product_ids <id>/--version_ids <id>(按工作流 A 步骤 1 的相同方式解析)。应用与工作流 B 步骤 2 相同的--updated_start_date/--updated_end_date优先于--start_date/--end_date的规则、结束日期扩展规则、日期计算规则和分页规则——很久以前分配给该成员、但仅在此时间范围内完成的工单,不能仅仅因为它不是在此期间创建的就被遗漏。 -
按照工作流 B 步骤 2a,每 50 个候选工单进行一次批量调用,以验证状态变更——
updated_at不等于“完成时间”的问题同样适用于单个成员的工单:cawplan tickets changes --unique_ids <candidate_ids_csv> --fields status --start_date <window_start> --end_date <window_end>不要对每个候选工单调用
tickets history。仅在tickets changes本身失败时,按照工作流 B 步骤 2a 的回退方案使用它(references/QUERY_RESILIENCE.md)。
输出
如果任何查询、页面、批次或时间范围未能完成,请在报告前说明已验证和未验证的内容(references/QUERY_RESILIENCE.md)。按照 references/QUERY_RESILIENCE.md §5 的规则撰写答复:不要包含 CLI 命令、内部字段名称或推理文本。
工作流 A:
- 摘要:此期间发生的变更和已完成的事项。
- 进度:工单完成率、状态分布。
- 风险:当前风险级别及原因(LOW / MEDIUM / HIGH)。
- 优先建议:发布前应处理的事项。
- 即将到来:目标发布日期和剩余未完成事项。
工作流 B:
- 摘要:此期间团队发生的变更(数量,而非风险判断——此工作流没有类似
versions track的风险字段;不要自行编造)。 - 完成情况:对于在此期间经历史记录验证发生状态变更的 Tickets,按状态、返回的标签和优先级统计数量;终态数量依据事件的新状态类别,而非原始
updated_at或当前状态单独判定。分类时不要使用旧版type。 - 值得关注的事项:在此期间实际发生状态变更的 CRITICAL/HIGH 优先级 Tickets,以及通过已验证的状态变更事件移至终态类别的任何 Ticket。
- 按产品分类:仅当步骤 3 已执行且用户要求时提供。
**工作流 C:**采用与工作流 B 相同的结构(摘要 + 完成情况 + 值得关注的事项),范围限定为该成员的工单——不包含按产品分类部分。
工作流 D:
- QA 活动摘要:时间范围内状态变更事件总数及涉及的不同 Tickets 数量。
- 按 QA 成员分类:每位与产品配置的
members.qas名单匹配的历史事件执行者的活动次数和不同 Ticket 数量;绝不能使用当前经办人或报告人作为分组字段。 - 验证过的状态转换:按
旧状态 → 新状态分组统计数量和 Ticket 佐证;状态已解决时还需按新状态类别分组,并包括 QA Testing、Done、Reopen、Close 及 API 返回的自定义状态。
参考资料
references/CAWPLAN_OPEN_API.mdreferences/QUERY_RESILIENCE.md