CawPlan Product Report
Bootstrap
cawplan skill check
Entry Routing
| Input |
Flow |
| A specific product (and optionally a version) |
A — Product report |
| Open/unclosed tickets in a product's current or named version |
A0 — Version open tickets |
| A Team / product line ("Team A", a squad/line name, not a product name) |
B — Team report |
| A product's UX members' UX/design completion |
Use cawplan-ux-tracking Workflow D; it counts ux → READY events performed by the product's configured Designers, not reporters or assignees. |
| A product's QA members' Ticket verification / acceptance status |
D — QA verification activities; count status-change events performed by that product's configured QA members, not by current Assignee. |
| A named member, someone other than the caller ("how's Alex doing on...") |
C — Member report |
If unsure whether a name is a product or a Team, resolve both (products list --search, product-lines list) and ask if either is ambiguous or both match. A user-supplied Team or product name must match an accessible record exactly (case-insensitively, after trimming whitespace), or be a unique short-form/token-prefix match. If it does not match uniquely, list the available or search-returned candidates and ask which Team/product they mean; never substitute a similarly named product or Team. If the user asks about their own task completion ("my tasks"), that's cawplan-my-work, not this skill.
Workflow A0 — Version open tickets
Use this workflow for requests such as “查看 VN Cloud 当前 Version 的 Open Tickets” or “list the unclosed tickets for Product X 1.2.3.” Apply Workflow A's required product-access gate before every other query. Do not infer a product from a similar name, alias, prior query, or another product's current version.
Resolve the requested product with:
cawplan products list --search "<product name or product_id>"
Continue only with an exact accessible-name match or a unique short-form/token-prefix match. If no candidate matches, report: “No accessible Product matched <input>; it may not exist, have a different name, or you may not have permission.” Do not query versions or tickets. If the API explicitly returns an access-denied error, report NO_PERMISSION; otherwise do not claim that lack of permission is certain.
Resolve the version. For “current Version,” use the matched product's inprogress_version_id and inprogress_version_name; if either is absent, report that the product has no current in-progress version. For a named version, use cawplan versions list <product_id> and require an exact version-name match. Never borrow a version from another product.
Fetch every ticket in that version, paging to total:
cawplan tickets search --version_ids <version_id> --start_date 2000-01-01 --end_date <today> --page_size 100 --page_num 1
Treat a ticket as open only when its inline status_display.category is neither COMPLETE nor CANCELED. Filter this client-side even if an --excluded_status_categories COMPLETE,CANCELED filter is also supplied; do not trust a server-side exclusion as the only safeguard.
Report the resolved Product and Version, total open count, and a status/priority breakdown. For each listed ticket, show display ID, type, priority, status, and title. If the result is too large for a useful chat response, provide the count and breakdown first, then ask for a priority/status slice or an export; do not silently substitute another product or report a partial list as complete.
Workflow A — Product report
Required product-access gate
Before querying any product-, version-, or ticket-scoped data, confirm that the requested product appears in the caller's products list response. Apply this gate even when the caller supplied a product ID directly or the ID was retained from earlier context.
cawplan products list --search "<product name or product_id>"
Proceed only after identifying one intended product (product_id / unique_id) through an exact match or unique short-form match. If the user's named product has no unique accessible match, stop and ask them to confirm the intended product from the candidates; do not issue product, version, activity, or ticket queries. Use NO_PERMISSION only when the API explicitly reports that access is denied. Never report an inaccessible or unresolved product as a successful empty result (for example, Open Tickets: 0).
Resolve product name to product_id and complete the required product-access gate:
cawplan products list --search "<product name>"
If no exact or unique short-form product match exists, list the candidates (name + product_id) and ask the user to confirm which product they mean; do not guess. If more than one match exists, ask the user to pick. All three workflows in this skill resolve products this way.
Resolve version name to version_id if the user scopes to a version:
cawplan versions list <product_id>
Fetch the product report:
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
Supplement with version progress when reporting on a specific version:
cawplan versions get <product_id> <version_id>
This provides progress.complete_percent, risk, risk_reason, and target_release.
Workflow B — Team report
There is no team-scoped activity endpoint — product-activity get only takes a single --product_id. Build the report from ticket changes across every product on the team instead.
Resolve the Team name to a product_line_id. product-lines list has no name filter, so page through it and match by name client-side:
cawplan product-lines list --page_size 100
If no name matches, ask for the correct name. If more than one matches, list the candidates (name + product_line_id, plus any other distinguishing field the response carries) and ask the user to pick — do not guess.
Fetch ticket changes across the whole team — this is the ticket-change data the report is built from:
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
- Use
--updated_start_date/--updated_end_date for the report window, not --start_date/--end_date — the latter filter ticket creation time, not last-changed time (see references/CAWPLAN_OPEN_API.md), so on their own they'd miss a ticket created earlier that was actually completed/progressed inside the window — silently understating "what changed." --start_date/--end_date still has to be passed (the endpoint requires a created_at window or --time_range), so pin it to a maximal range (2000-01-01 to today, the same workaround cawplan-ux-tracking uses) so it doesn't itself narrow results — --updated_start_date/--updated_end_date does the actual filtering.
- Pass
--updated_end_date <today> (real "today"), not the report window's own end date — updated_at is refreshed by any field change, not just completion, so a ticket that completed inside the window but got an unrelated edit (version transfer, priority bump, comment) after the window would have its updated_at pushed past the window's end and be silently dropped if --updated_end_date were capped there (see the updated_at-is-not-"completed at" note in references/CAWPLAN_OPEN_API.md). Widening the end bound to today makes this a candidate set, not the final answer — step 2a below narrows it back down using the real completion time for anything currently done/canceled. A ticket created inside [window_start, today] is still caught (its updated_at starts equal to created_at), so this remains a strict superset of the old created_at-only behavior.
- For "last N days" asks, compute
--updated_start_date (today minus N days) client-side — time_range only applies to the created_at pair, not the updated_at pair.
- The response is a
CommonPageResp (data, page_num, page_size, total) — page through while page_num * page_size < total, the same rule used in cawplan-my-work/cawplan-ux-tracking for this identical shape. Don't stop on a page that happens to come back full without checking total first.
2a. Narrow the candidate set to actual status changes in the report window — updated_at
is only a broad candidate filter: it is refreshed by any edit, including recomputing a Parent
Ticket after one of its Sub-tickets changes. It is never evidence that this Ticket changed
status.
- For every candidate, call
cawplan tickets history <product_id> <version_id> <ticket_id>.
Keep the Ticket only when an UPDATED history entry has changed_fields.status and that
entry's created_at is inside [window_start, window_end]. Do not keep a Ticket solely
because its updated_at is in the window, and do not treat its CREATED entry as a status
change.
changed_fields.status can be either the new status key string, or an object with old and
new; handle both shapes. Resolve the relevant product line's status definitions when a
terminal-completion breakdown is needed, then classify the event's new status by category
(COMPLETE / CANCELED), rather than hard-coding DONE.
- Count each Ticket once in the summary, retaining its latest in-window status-change event as
the displayed evidence. A Parent Ticket whose status did not change has no such history entry
and must be excluded even if a Sub-ticket change refreshed the Parent's
updated_at.
- This adds one
tickets history call per candidate. It is deliberate: the search endpoint
cannot distinguish a status change from an unrelated record edit.
- Optionally, resolve which products make up the team (for a per-product breakdown only if asked):
cawplan products list --product_line_id <product_line_id>
Workflow D — QA verification activities
Use this workflow for requests such as “汇总 CawCut Cloud 的 QA Team 本周的 Ticket 验收情况” or
“Summarize this product's QA ticket verification status.” Here, QA Team means the product's
configured members.qas roster, not a CawPlan product line. If the product is omitted, ask
which product's QA members should be reported. This workflow measures QA Activities: actual
Ticket status transitions performed by a QA member during the requested period. It does not use
current Assignee, Reporter, or a Ticket's current status as a proxy for QA work.
Resolve the product and complete Workflow A's required product-access gate:
cawplan products list --search "<product name or product_id>"
Read the matched product's members.qas[] roster and collect its user_id values and display
names. If it has no QA members, report that the product has no configured QA roster and stop.
Membership is product-scoped; use the roster returned for this product, not a workspace-wide
keyword search. Default an omitted range to the current week and state the inclusive date range
used.
Build a complete candidate set exactly as in Workflow B step 2, including pagination:
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 only identifies Tickets whose history may be relevant. Its end bound must remain
real today, not the report end date, because a later unrelated edit must not hide an earlier QA
activity.
For every candidate, call:
cawplan tickets history <product_id> <version_id> <ticket_id>
Keep every UPDATED entry whose changed_fields.status is present, whose created_at is
inside [window_start, window_end], and whose history-entry user_id belongs to the resolved
members.qas roster. Do not count CREATED, TRANSFERRED, an arbitrary updated_at, a
status change performed by a non-QA actor, or a Ticket merely because it is currently assigned
to QA. The status field is normally {old, new}; tolerate a legacy string value as the new
status.
Treat each retained history entry as one QA activity — do not deduplicate by Ticket. A
Ticket can legitimately be moved through QA Testing, Done, Reopen, and Close within one week;
each status transition is useful verification evidence. Attribute the activity to the history
entry's user_id / user_display_name, the QA person who performed the change. Do not infer
that person from the Ticket's Reporter or Assignee. Exclude an entry with no actor that cannot
be matched to the product QA roster; identify it separately as an unassigned/integration event
only if relevant to explaining the exclusion.
Resolve the product line's status definitions when a category breakdown is requested. Display
the actual transition (old → new) and, when available, its new-status category. Do not
hard-code DONE, REOPEN, CLOSE, or QA Testing: custom status keys and categories are
valid QA activities too.
Workflow C — Member report
Same ticket-change approach as Workflow B, scoped to one person instead of a whole product line.
Resolve the member to a user_id:
cawplan users query --email <email> # if the user gave an email
cawplan users query --keyword "<name>" # if the user gave a name
If the keyword query returns more than one person, list them (name + email) and ask which one — do not guess.
Fetch their ticket changes in the period:
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
If the user also scoped to a product/version, add --product_ids <id> / --version_ids <id> (resolve the same way as Workflow A step 1). Apply the same --updated_start_date/--updated_end_date-over---start_date/--end_date rule, widened-end-date, date-computation, and pagination rules as Workflow B step 2 — a ticket assigned to this member long ago but only completed inside the window must not be missed just because it wasn't created inside it. Then apply Workflow B step 2a (history-verified completion window) to this candidate set before reporting completion counts — the updated_at-is-not-"completed at" issue applies identically to a single member's tickets.
Output
Workflow A:
- Summary: what changed and what was completed in the period.
- Progress: ticket completion rate, status breakdown.
- Risk: current risk level and reason (LOW / MEDIUM / HIGH).
- Priority recommendations: what should be addressed before release.
- Upcoming: target release dates and remaining open items.
Workflow B:
- Summary: what changed across the team in the period (counts, not a risk verdict — this workflow has no
versions track-style risk field; don't invent one).
- Completion: counts by status, type, and priority for Tickets with a history-verified status change in the period; terminal counts are based on the event's new status category, never raw
updated_at or current status alone.
- Notable items: CRITICAL/HIGH priority Tickets that actually changed status in the period, plus any Ticket moved to a terminal category by its verified status-change event.
- Per-product breakdown: only if step 3 ran and the user asked for it.
Workflow C: same shape as Workflow B (Summary + Completion + Notable items), scoped to the one person's tickets — no per-product breakdown section.
Workflow D:
- QA activity summary: total in-window status-change events and distinct Tickets involved.
- By QA member: activity count and distinct Ticket count per history-event actor that matches
the product's configured
members.qas roster; never use current Assignee or Reporter as the
grouping field.
- Verification transitions: counts and Ticket evidence grouped by
old → new status (and
new-status category when resolved), including QA Testing, Done, Reopen, Close, and custom
statuses as returned by the API.
References
references/CAWPLAN_OPEN_API.md
1---2name: cawplan-product-report3description: Generate a CawPlan status report over a date range: for a single product (progress, risk analysis, priority recommendations, summaries), for a Team (CawPlan product line), or for a named member — ticket-change-based completion, in the last two cases. Use when: the user asks for a product status report, progress report, risk summary, release readiness, priority recommendations, or the open/unclosed tickets in a product's current or named version; asks how a Team/product line is doing over a date range; or asks how a specific member's task completion looks over a date range (not their own — use `cawplan-my-work` for "my tasks"). NOT for: raw activity feed, user activity, ticket creation, metrics dashboards, or critical issue lists.4---56# CawPlan Product Report78## Bootstrap910```bash11cawplan skill check12```1314## Entry Routing1516| Input | Flow |17|---|---|18| A specific product (and optionally a version) | **A — Product report** |19| Open/unclosed tickets in a product's current or named version | **A0 — Version open tickets** |20| A Team / product line ("Team A", a squad/line name, not a product name) | **B — Team report** |21| A product's UX members' UX/design completion | Use `cawplan-ux-tracking` **Workflow D**; it counts `ux → READY` events performed by the product's configured Designers, not reporters or assignees. |22| A product's QA members' Ticket verification / acceptance status | **D — QA verification activities**; count status-change events performed by that product's configured QA members, not by current Assignee. |23| A named member, someone other than the caller ("how's Alex doing on...") | **C — Member report** |2425If unsure whether a name is a product or a Team, resolve both (`products list --search`, `product-lines list`) and ask if either is ambiguous or both match. A user-supplied Team or product name must match an accessible record exactly (case-insensitively, after trimming whitespace), or be a unique short-form/token-prefix match. If it does not match uniquely, list the available or search-returned candidates and ask which Team/product they mean; never substitute a similarly named product or Team. If the user asks about their *own* task completion ("my tasks"), that's `cawplan-my-work`, not this skill.2627## Workflow A0 — Version open tickets2829Use this workflow for requests such as “查看 VN Cloud 当前 Version 的 Open Tickets” or “list the unclosed tickets for Product X 1.2.3.” Apply **Workflow A's required product-access gate before every other query**. Do not infer a product from a similar name, alias, prior query, or another product's current version.30311. Resolve the requested product with:32 ```bash33 cawplan products list --search "<product name or product_id>"34 ```35 Continue only with an exact accessible-name match or a unique short-form/token-prefix match. If no candidate matches, report: “No accessible Product matched `<input>`; it may not exist, have a different name, or you may not have permission.” Do not query versions or tickets. If the API explicitly returns an access-denied error, report `NO_PERMISSION`; otherwise do not claim that lack of permission is certain.36372. Resolve the version. For “current Version,” use the matched product's `inprogress_version_id` and `inprogress_version_name`; if either is absent, report that the product has no current in-progress version. For a named version, use `cawplan versions list <product_id>` and require an exact version-name match. Never borrow a version from another product.38393. Fetch every ticket in that version, paging to `total`:40 ```bash41 cawplan tickets search --version_ids <version_id> --start_date 2000-01-01 --end_date <today> --page_size 100 --page_num 142 ```43 Treat a ticket as open only when its inline `status_display.category` is neither `COMPLETE` nor `CANCELED`. Filter this client-side even if an `--excluded_status_categories COMPLETE,CANCELED` filter is also supplied; do not trust a server-side exclusion as the only safeguard.44454. Report the resolved Product and Version, total open count, and a status/priority breakdown. For each listed ticket, show display ID, type, priority, status, and title. If the result is too large for a useful chat response, provide the count and breakdown first, then ask for a priority/status slice or an export; do not silently substitute another product or report a partial list as complete.4647## Workflow A — Product report4849### Required product-access gate5051Before querying **any** product-, version-, or ticket-scoped data, confirm that the requested product appears in the caller's `products list` response. Apply this gate even when the caller supplied a product ID directly or the ID was retained from earlier context.5253```bash54cawplan products list --search "<product name or product_id>"55```5657Proceed only after identifying one intended product (`product_id` / `unique_id`) through an exact match or unique short-form match. If the user's named product has no unique accessible match, stop and ask them to confirm the intended product from the candidates; do not issue product, version, activity, or ticket queries. Use `NO_PERMISSION` only when the API explicitly reports that access is denied. Never report an inaccessible or unresolved product as a successful empty result (for example, `Open Tickets: 0`).58591. Resolve product name to `product_id` and complete the required product-access gate:60 ```bash61 cawplan products list --search "<product name>"62 ```63 If no exact or unique short-form product match exists, list the candidates (name + `product_id`) and ask the user to confirm which product they mean; do not guess. If more than one match exists, ask the user to pick. All three workflows in this skill resolve products this way.64652. Resolve version name to `version_id` if the user scopes to a version:66 ```bash67 cawplan versions list <product_id>68 ```69703. Fetch the product report:71 ```bash72 cawplan product-activity get \73 --product_id <product_id> \74 --start YYYY-MM-DD \75 --end YYYY-MM-DD7677 # Scoped to a specific version:78 cawplan product-activity get \79 --product_id <product_id> \80 --version_id <version_id> \81 --start YYYY-MM-DD \82 --end YYYY-MM-DD83 ```84854. Supplement with version progress when reporting on a specific version:86 ```bash87 cawplan versions get <product_id> <version_id>88 ```89 This provides `progress.complete_percent`, `risk`, `risk_reason`, and `target_release`.9091## Workflow B — Team report9293There is no team-scoped activity endpoint — `product-activity get` only takes a single `--product_id`. Build the report from ticket changes across every product on the team instead.94951. Resolve the Team name to a `product_line_id`. `product-lines list` has no name filter, so page through it and match by name client-side:96 ```bash97 cawplan product-lines list --page_size 10098 ```99 If no name matches, ask for the correct name. If more than one matches, list the candidates (name + `product_line_id`, plus any other distinguishing field the response carries) and ask the user to pick — do not guess.1001012. Fetch ticket changes across the whole team — this is the ticket-change data the report is built from:102 ```bash103 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 1104 ```105 - **Use `--updated_start_date`/`--updated_end_date` for the report window, not `--start_date`/`--end_date`** — the latter filter ticket *creation* time, not last-changed time (see `references/CAWPLAN_OPEN_API.md`), so on their own they'd miss a ticket created earlier that was actually completed/progressed inside the window — silently understating "what changed." `--start_date`/`--end_date` still has to be passed (the endpoint requires a created_at window or `--time_range`), so pin it to a maximal range (`2000-01-01` to today, the same workaround `cawplan-ux-tracking` uses) so it doesn't itself narrow results — `--updated_start_date`/`--updated_end_date` does the actual filtering.106 - **Pass `--updated_end_date <today>` (real "today"), not the report window's own end date** — `updated_at` is refreshed by *any* field change, not just completion, so a ticket that completed inside the window but got an unrelated edit (version transfer, priority bump, comment) after the window would have its `updated_at` pushed past the window's end and be silently dropped if `--updated_end_date` were capped there (see the `updated_at`-is-not-"completed at" note in `references/CAWPLAN_OPEN_API.md`). Widening the end bound to today makes this a candidate set, not the final answer — step 2a below narrows it back down using the real completion time for anything currently done/canceled. A ticket created inside `[window_start, today]` is still caught (its `updated_at` starts equal to `created_at`), so this remains a strict superset of the old created_at-only behavior.107 - For "last N days" asks, compute `--updated_start_date` (today minus N days) client-side — `time_range` only applies to the created_at pair, not the updated_at pair.108 - The response is a `CommonPageResp` (`data`, `page_num`, `page_size`, `total`) — page through while `page_num * page_size < total`, the same rule used in `cawplan-my-work`/`cawplan-ux-tracking` for this identical shape. Don't stop on a page that happens to come back full without checking `total` first.1091102a. **Narrow the candidate set to actual status changes in the report window** — `updated_at`111 is only a broad candidate filter: it is refreshed by any edit, including recomputing a Parent112 Ticket after one of its Sub-tickets changes. It is never evidence that this Ticket changed113 status.114 - For **every** candidate, call `cawplan tickets history <product_id> <version_id> <ticket_id>`.115 Keep the Ticket only when an `UPDATED` history entry has `changed_fields.status` and that116 entry's `created_at` is inside `[window_start, window_end]`. Do not keep a Ticket solely117 because its `updated_at` is in the window, and do not treat its `CREATED` entry as a status118 change.119 - `changed_fields.status` can be either the new status key string, or an object with `old` and120 `new`; handle both shapes. Resolve the relevant product line's status definitions when a121 terminal-completion breakdown is needed, then classify the event's **new** status by category122 (`COMPLETE` / `CANCELED`), rather than hard-coding `DONE`.123 - Count each Ticket once in the summary, retaining its latest in-window status-change event as124 the displayed evidence. A Parent Ticket whose status did not change has no such history entry125 and must be excluded even if a Sub-ticket change refreshed the Parent's `updated_at`.126 - This adds one `tickets history` call per candidate. It is deliberate: the search endpoint127 cannot distinguish a status change from an unrelated record edit.1281293. Optionally, resolve which products make up the team (for a per-product breakdown only if asked):130 ```bash131 cawplan products list --product_line_id <product_line_id>132 ```133134## Workflow D — QA verification activities135136Use this workflow for requests such as “汇总 CawCut Cloud 的 QA Team 本周的 Ticket 验收情况” or137“Summarize this product's QA ticket verification status.” Here, **QA Team means the product's138configured `members.qas` roster**, not a CawPlan product line. If the product is omitted, ask139which product's QA members should be reported. This workflow measures **QA Activities**: actual140Ticket status transitions performed by a QA member during the requested period. It does not use141current Assignee, Reporter, or a Ticket's current status as a proxy for QA work.1421431. Resolve the product and complete Workflow A's required product-access gate:144 ```bash145 cawplan products list --search "<product name or product_id>"146 ```147 Read the matched product's `members.qas[]` roster and collect its `user_id` values and display148 names. If it has no QA members, report that the product has no configured QA roster and stop.149 Membership is product-scoped; use the roster returned for this product, not a workspace-wide150 keyword search. Default an omitted range to the current week and state the inclusive date range151 used.1521532. Build a complete candidate set exactly as in Workflow B step 2, including pagination:154 ```bash155 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 1156 ```157 `updated_at` only identifies Tickets whose history may be relevant. Its end bound must remain158 real today, not the report end date, because a later unrelated edit must not hide an earlier QA159 activity.1601613. For **every** candidate, call:162 ```bash163 cawplan tickets history <product_id> <version_id> <ticket_id>164 ```165 Keep every `UPDATED` entry whose `changed_fields.status` is present, whose `created_at` is166 inside `[window_start, window_end]`, and whose history-entry `user_id` belongs to the resolved167 `members.qas` roster. Do not count `CREATED`, `TRANSFERRED`, an arbitrary `updated_at`, a168 status change performed by a non-QA actor, or a Ticket merely because it is currently assigned169 to QA. The status field is normally `{old, new}`; tolerate a legacy string value as the new170 status.1711724. Treat each retained history entry as one QA activity — do **not** deduplicate by Ticket. A173 Ticket can legitimately be moved through QA Testing, Done, Reopen, and Close within one week;174 each status transition is useful verification evidence. Attribute the activity to the history175 entry's `user_id` / `user_display_name`, the QA person who performed the change. Do not infer176 that person from the Ticket's Reporter or Assignee. Exclude an entry with no actor that cannot177 be matched to the product QA roster; identify it separately as an unassigned/integration event178 only if relevant to explaining the exclusion.1791805. Resolve the product line's status definitions when a category breakdown is requested. Display181 the actual transition (`old → new`) and, when available, its new-status category. Do not182 hard-code `DONE`, `REOPEN`, `CLOSE`, or `QA Testing`: custom status keys and categories are183 valid QA activities too.184185## Workflow C — Member report186187Same ticket-change approach as Workflow B, scoped to one person instead of a whole product line.1881891. Resolve the member to a `user_id`:190 ```bash191 cawplan users query --email <email> # if the user gave an email192 cawplan users query --keyword "<name>" # if the user gave a name193 ```194 If the keyword query returns more than one person, list them (name + email) and ask which one — do not guess.1951962. Fetch their ticket changes in the period:197 ```bash198 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 1199 ```200 If the user also scoped to a product/version, add `--product_ids <id>` / `--version_ids <id>` (resolve the same way as Workflow A step 1). Apply the same `--updated_start_date`/`--updated_end_date`-over-`--start_date`/`--end_date` rule, widened-end-date, date-computation, and pagination rules as Workflow B step 2 — a ticket assigned to this member long ago but only completed inside the window must not be missed just because it wasn't *created* inside it. Then apply **Workflow B step 2a** (history-verified completion window) to this candidate set before reporting completion counts — the `updated_at`-is-not-"completed at" issue applies identically to a single member's tickets.201202## Output203204**Workflow A:**205206- **Summary**: what changed and what was completed in the period.207- **Progress**: ticket completion rate, status breakdown.208- **Risk**: current risk level and reason (LOW / MEDIUM / HIGH).209- **Priority recommendations**: what should be addressed before release.210- **Upcoming**: target release dates and remaining open items.211212**Workflow B:**213214- **Summary**: what changed across the team in the period (counts, not a risk verdict — this workflow has no `versions track`-style risk field; don't invent one).215- **Completion**: counts by status, type, and priority for Tickets with a history-verified status change in the period; terminal counts are based on the event's new status category, never raw `updated_at` or current status alone.216- **Notable items**: CRITICAL/HIGH priority Tickets that actually changed status in the period, plus any Ticket moved to a terminal category by its verified status-change event.217- **Per-product breakdown**: only if step 3 ran and the user asked for it.218219**Workflow C:** same shape as Workflow B (Summary + Completion + Notable items), scoped to the one person's tickets — no per-product breakdown section.220221**Workflow D:**222223- **QA activity summary**: total in-window status-change events and distinct Tickets involved.224- **By QA member**: activity count and distinct Ticket count per history-event actor that matches225 the product's configured `members.qas` roster; never use current Assignee or Reporter as the226 grouping field.227- **Verification transitions**: counts and Ticket evidence grouped by `old → new` status (and228 new-status category when resolved), including QA Testing, Done, Reopen, Close, and custom229 statuses as returned by the API.230231## References232233- `references/CAWPLAN_OPEN_API.md`