CawPlan My Work
Bootstrap
cawplan skill check
Workflow
Resolve your own
user_id— this is decoded from your local access token, no network call needed:cawplan auth statusRead the
User ID:line from the output. If it's missing, re-authenticate (cawplan auth login) rather than falling back tocawplan users query --email— that would spend a network call resolving somethingauth statusshould already have.Fetch your todos:
cawplan todos user <user_id>This returns
tickets(grouped byproduct_line→product→version),critical_issues(grouped byproduct_line→product), andsummary. No status filter is applied by default — the response includes everything assigned to you, not just open items.If the user named a specific project/version, narrow
ticketsto that exactproduct→versionleaf.critical_issueshas no version dimension (onlyproduct_line→product), so it can't be narrowed to the same granularity — when the user named a version, narrowcritical_issuesto the matching product only, and say explicitly that these critical issues are product-wide and not confirmed to be specific to the named version. If the named project/version doesn't appear anywhere intickets, say so explicitly ("no tickets found for you under ") rather than falling back to showing everything.If the user asks for only open/未完成 items, resolve status categories for every distinct product line present in the response and filter properly — this is your own work, so it's realistically a handful of lines, not worth shortcutting:
cawplan product-lines statuses <product_line_id> # once per distinct product line in the responseExclude tickets whose status key maps to category
COMPLETEorCANCELED. Only fall back to "just show every item's status clearly instead, let the user judge" if this turns out to span more product lines than is reasonable to resolve (rare for one person's own work) — and say explicitly that's what you're doing rather than silently presenting an unfiltered list as if it were filtered.Priority-sorted flat list (only when the user asks for "my open tickets by priority" / sorted-by-priority framing, rather than a project/version breakdown): flatten
ticketsacross every product line/product/version into one list. This framing implies open-only even if not stated explicitly — run step 4's filtering for it. Then sortCRITICAL→HIGH→MEDIUM→LOW. Still show which product/version each ticket belongs to per row — flattening the grouping for sort order doesn't mean dropping that context.
5a. My task completion / status-change summary for a day or range (only when the user asks “帮我总结今天的任务完成情况”, “今天哪些任务状态变更了”, or equivalent): this is not the current-todos view in step 2. Default the window to today; honor an explicit date/range.
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
Page through fully using total. The updated_at window supplies candidates only: a Parent
Ticket can be refreshed because a Sub-ticket changed, even when the Parent's own status did not.
For every candidate, fetch:
cawplan tickets history <product_id> <version_id> <ticket_id>
Keep a Ticket only if an UPDATED history entry contains changed_fields.status and its
created_at is in the requested window. changed_fields.status may be a new-status string or
an {old, new} object; support both. Do not use updated_at as final evidence and do not count
CREATED as a status change. Report each Ticket once, using its latest in-window status-change
entry; exclude an unchanged Parent Ticket even if a child transition refreshed its record.
My reopened tickets (only when the user asks about reopened tickets / why something got reopened): there's no
REOPENEDstatus category (onlyUNSTARTED/STARTED/TESTING/COMPLETE/CANCELED) — reopening shows up as a status key whose name says so, or as a history transition backward out of a terminal category. History-scanning (bullet 2) is always the ground truth; the status-key check (bullet 1) is only a shortcut for the common case where a ticket is currently sitting on the reopen status — it does not replace history-scanning.- Check history for every one of your tickets, regardless of current status:
cawplan tickets history <product_id> <version_id> <ticket_id>, looking for any transition from aCOMPLETE/CANCELED-category status back to a non-terminal category — each such transition is a reopen event. A ticket can have more than one; report all of them (oldest to newest), not just the latest — don't assume a ticket is reopened at most once. - As a labeling aid only, resolve each distinct product line's statuses (
cawplan product-lines statuses <product_line_id>) to check whether the ticket's status right after a reopen transition has "reopen" in itsdisplay_name— if so you can call it out as "reopened" by name in the report; if not (e.g. it went straight back toin_progressorTESTING), it's still a reopen per the history transition, just report the actual status name instead of assuming there's a dedicated label for it. - For each reopen event, report the timestamp and actor from that history entry if present, and the reason: use the history entry's own comment if the API returns one on status-change events and it's plausibly about that specific transition (a general free-text comment field that isn't tied to the transition shouldn't be presented as if it explains the reopen); otherwise fall back to the ticket's
progress_commentand label it explicitly as "latest progress note, not necessarily the reopen reason" rather than presenting it as if it directly explains the reopen. If neither exists, say the reason wasn't recorded — do not infer a reason from the ticket title or description. If thetickets historycall itself fails or returns nothing, treat that ticket the same as "no reopen found," not as evidence of a missing reason.
- Check history for every one of your tickets, regardless of current status:
My tickets' linked repo PRs/commits (only when asked — "today's tickets with their PR/commits", "整理我当天任务涉及的tickets和PR/commit"): tickets carry a
links[]array that can hold GitHub PR/commit URLs (shape documented inreferences/CAWPLAN_OPEN_API.mdunder "VersionTicket fields of note") —todos/polldon't return this field, only the full ticket record does, so this step usestickets searchinstead of steps 1-6'stodoscall.cawplan tickets search --assignees <user_id> --start_date 2000-01-01 --end_date <today> --updated_start_date <date> --updated_end_date <date> --page_size 100 --page_num 1Default
<date>-<date>to today for both--updated_start_date/--updated_end_dateunless the user asked for a different day/range; treat the end date as inclusive of the whole day unless a result set proves otherwise. Use--updated_start_date/--updated_end_date, not--start_date/--end_date, for "today's tickets" — the latter filter ticket creation time (confirmed againstuid.core-product's DAO, seereferences/CAWPLAN_OPEN_API.md), so a ticket created last week that you're actively working on today would be silently missed.--start_date/--end_datestill has to be passed (the endpoint requires a created_at window or--time_range) — pin it to the maximal-window workaround (2000-01-01to today) so it doesn't itself narrow the result.platformon a link isn't a reliable fixed value — the same manually-added GitHub link can show up asplatform: "LINK"— so classify by theurlitself: contains/pull/→ PR, contains/commit/→ commit, otherwise report it as a plain link with itstitle. A ticket with an emptylinksarray has no repo links; say so rather than omitting it from the report. Page through using the response'stotal/page_num/page_sizefields (keep fetching whilepage_num * page_size < total) rather than assuming one page of 100 covers everything.Ticket has a PR/commit linked but status hasn't moved (only when asked — "哪些ticket已经有PR/commit但状态还没更新"): reuse step 7's fetch mechanism and pagination rule, adding
--status_categories UNSTARTED,STARTED. Scope: if the user names a product/version, use--product_ids/--version_idsin place of--assignees; if they explicitly say "my"/自己的, use--assignees <user_id>. If they specify neither, default to your own tickets (--assignees <user_id>) and say so. Use--start_date 2000-01-01 --end_date <today>because stale tickets may not be recent.- A ticket "has a PR/commit" when any of its
linkshas aurlcontaining/pull/or/commit/— either one counts, since an open PR (not yet merged into a commit reference) is just as much a sign of active code work as a bare commit link. - Report each qualifying ticket with the PR/commit link(s) found (and whether each is a PR or a commit, same classification as step 7) and its current status, so the user can judge whether the ticket genuinely needs a status bump.
- A ticket "has a PR/commit" when any of its
Output
- Group by product line → product → version, matching the API's own grouping — don't re-flatten it into one undifferentiated list, unless step 5 ran, in which case present the single priority-sorted list instead (still showing product/version per row).
- For each ticket: display ID, type, priority, status, one-line title.
- Critical issues: separate section, grouped by product line → product, with severity/status.
- Lead with
summaryif the response includes one and step 3 didn't narrow the scope —summarydescribes the full unnarrowed response, so showing it alongside a narrowed list would contradict what's actually listed. When narrowed, state counts for the narrowed slice instead (e.g. "1 ticket, 1 product-wide critical issue for UniFi Access 4.1.10"). - If step 3 narrowed the scope, say what it was narrowed to before listing results.
- If there's genuinely nothing assigned, say so plainly rather than returning an empty section with no comment.
- If step 6 ran: one entry per reopened ticket (display ID, title, reopened-at, reopened-by if known, reason or "not recorded"). If none of your tickets were reopened, say so explicitly rather than showing an empty list.
- If step 7 ran: one entry per ticket in the fetched window, its PRs/commits/other links (or "no repo links"); note the date-field assumption once, not per ticket.
- If step 8 ran: one entry per qualifying ticket — display ID, title, current status, and the PR/commit link(s) that triggered the flag. If none qualify, say so explicitly.
- If step 5a ran: list only history-verified status changes, with display ID, title, old → new status when available, change timestamp, and whether the new status is terminal. State that unchanged Parent Tickets are intentionally excluded.
References
references/CAWPLAN_OPEN_API.md