mcpField
C
cawplan-product-report

cawplan-product-report

github.com/cawcut生产力1144 次安装2 天前更新
代码仓库

关于 cawplan-product-report

CawPlan Product Report 是基于 CawPlan 工单和活动生成产品、版本、团队及成员报告的技能。它按请求类型路由查询流程,并强调准确匹配记录及可核查的工单分类。

主要功能

  1. 01产品与版本活动报告
  2. 02汇总团队工单变更
  3. 03按标签分类工单
  4. 04统计状态、经办人和优先级
  5. 05报告重新打开事件
  6. 06精确匹配产品与工单标题

适用场景

  1. 01查看产品版本的未关闭工单
  2. 02跨版本查找特定类别工单
  3. 03汇总产品团队的活动
  4. 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 的必需产品访问权限检查。不得根据相似名称、别名、之前的查询或其他产品的当前版本推断产品。

  1. 使用以下命令解析请求中的产品:

    cawplan products list --search <product-name-word-or-product_id>
    

    将搜索文本作为一个不带引号的标记传入(使用 --search CawPlan,绝不要使用 --search "CawPlan"):托管 Agent 会拒绝带引号的值。对于包含空格的名称,请搜索一个有辨识度的词,并在结果中匹配完整名称。 仅在名称完全匹配且可访问,或唯一的简称/令牌前缀匹配时继续。如果没有候选项匹配,请报告:“没有与 <input> 匹配的可访问 Product;它可能不存在、名称不同,或你可能没有权限。”不要查询版本或工单。如果 API 明确返回访问被拒绝错误,请报告 NO_PERMISSION;否则,不要断言一定是权限不足。

  2. 解析版本。对于“当前 Version”,使用匹配产品的 inprogress_version_id 和 inprogress_version_name;如果其中任一项缺失,请报告该产品没有当前进行中的版本。对于指定版本,请使用 cawplan versions list <product_id>,并要求版本名称完全匹配。绝不要借用其他产品的版本。

  3. 获取该版本中的所有工单,分页直至达到 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 筛选条件,也必须在客户端进行筛选;不能仅依赖服务端排除作为唯一保障。

  4. 报告解析出的 Product 和 Version、未关闭工单总数,以及状态/优先级明细。对于每张列出的工单,显示展示 ID、标签、优先级、状态以及原样的 description 标题。如果结果过多,不适合在聊天回复中完整呈现,请先提供数量和明细,再询问是否需要按优先级/状态筛选或导出;不得暗中替换为其他产品,也不得将不完整列表报告为完整列表。

工作流 A1 — 按标签筛选产品范围内的工单

对于“列出 VN iOS 的剩余 Collage Bug”等请求,请使用此工作流。除非用户明确缩小范围,否则查询范围会有意涵盖进行中的版本和 Backlog。

  1. 确认请求中的产品,并完成工作流 A 的必需产品访问权限检查。保留已确认的 product_id;不要根据名称相似来推断产品。

  2. 获取该产品可见的完整标签目录:

    cawplan labels list --product_id <product_id> --page_size 200 --page_num 1
    

    翻页直至 total。此产品范围内的目录包含通过其团队/产品线适用的标签,以及任何工作区级标签。只能从实际返回的记录中选择;绝不要编造标签名称或 ID,也不要用未限定范围的工作区级目录代替。

  3. 将用户请求的类别与返回的目录进行匹配。比较时统一大小写、空格、连字符和下划线,但保留返回的确切标签 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。
  4. 查询所有匹配的工单。使用步骤 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。

  5. 仅当每条结果内联的 status_display.category 既不是 COMPLETE 也不是 CANCELED 时,才在客户端独立归类为未关闭;TESTING 仍视为未关闭。即使服务器已提供排除条件,这项客户端检查仍是必需的。

  6. 确保分类结果可核查。在结果表格之前,列出确切选中的标签(名称、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)。

  1. 将产品名称解析为 product_id,并完成必要的产品访问权限检查:

    cawplan products list --search <product-name-word>
    

    如果没有精确匹配或唯一的简称匹配,请列出候选项(名称 + product_id),并询问用户想查询哪个产品;不要猜测。此技能中的所有产品范围工作流都必须按此方式解析产品。

  2. 如果用户指定了版本范围,则将版本名称解析为 version_id:

    cawplan versions list <product_id>
    
  3. 获取产品报告:

    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
    
  4. 报告特定版本时,补充版本进度信息:

    cawplan versions get <product_id> <version_id>
    

    这会提供 progress.complete_percent、risk、risk_reason 和 target_release。

工作流 B — 团队报告

没有团队范围的活动端点 — product-activity get 仅接受单个 --product_id。因此,请从团队中每个产品的工单变更构建报告。

  1. 将团队名称解析为 product_line_id。product-lines list 不支持按名称筛选,因此请遍历所有分页,并在客户端按名称匹配:

    cawplan product-lines list --page_size 100
    

    如果没有名称匹配项,请询问正确的名称。如果匹配项不止一个,请列出候选项(名称 + product_line_id,以及响应中包含的其他任何区分字段),并请用户选择;不要猜测。

  2. 获取整个团队的工单变更 — 这是报告所依据的工单变更数据:

    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 视为状态变更。解析产品线的状态定义,根据类别对新状态进行分类。说明使用了较慢的 路径;如果无法检查所有候选项,则报告部分结果。
  3. 可选:解析团队由哪些产品构成(仅在用户要求按产品细分时):

    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 工作。

  1. 确定产品,并完成工作流 A 要求的产品访问权限检查:

    cawplan products list --search <product-name-word-or-product_id>
    

    读取匹配产品的 members.qas[] 名单,并收集其中的 user_id 值和显示名称。如果没有 QA 成员,请报告该产品未配置 QA 名单并停止。成员资格以产品为范围;请使用该产品返回的名单,而非在整个工作区进行关键字搜索。如果未指定日期范围,默认使用本周,并注明所采用的起止日期(含首尾)。

  2. 使用一次批量调用,获取该 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 继续获取,或拆分时间窗口。

  3. 回退方案(仅当 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 名单。请说明使用了较慢的方式;如果未能检查所有候选项,请报告部分结果。

  4. 将每条保留的历史记录视为一项 QA 活动——不要按 Ticket 去重。一个 Ticket 在一周内可能会依次经历 QA Testing、Done、Reopen 和 Close;每次状态变更都能提供有用的验证证据。将活动归属给事件的 actor(或回退方案中历史记录的 user_id / user_display_name),即执行变更的 QA 成员。不要根据 Ticket 的 Reporter 或 Assignee 推断该成员。如果条目没有 actor,且无法与产品 QA 名单中的成员匹配,则排除该条目;只有在有助于解释排除原因时,才单独将其标记为未分配/集成事件。

  5. 如需按类别细分,请使用各事件的 new_category;仅在回退方案中解析产品线的状态定义。显示实际状态变更(old → new),并在可用时显示新状态类别。不要将 DONE、REOPEN、CLOSE 或 QA Testing 硬编码为状态;自定义状态键和类别也属于有效的 QA 活动。

工作流 C — 成员报告

采用与工作流 B 相同的工单变更方法,但范围限定为一个人,而不是整条产品线。

  1. 将成员解析为 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
    

    如果关键词查询返回多个人员,请列出他们(姓名 + 邮箱),并询问用户要选哪一位——不要猜测。

  2. 获取该成员在此期间的工单变更:

    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 的规则、结束日期扩展规则、日期计算规则和分页规则——很久以前分配给该成员、但仅在此时间范围内完成的工单,不能仅仅因为它不是在此期间创建的就被遗漏。

  3. 按照工作流 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.md
  • references/QUERY_RESILIENCE.md

评论

支持 Markdown