skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
cawcut/skill-cawplan102 installs

cawplan-my-work

Show the current user's CawPlan work: assigned tickets/critical issues, priority-sorted open tickets, a day/range status-change completion summary, reopened tickets, linked PRs/commits, or tickets with a PR/commit but no status progress — optionally scoped to a product/version. Use when: the user asks for my work/tasks/tickets, my open tickets by priority, a summary of today's/recent task completion or status changes, reopened tickets, today's ticket PRs/commits, or tickets with a PR/commit but no status update. NOT for another person's work, broad ticket search/filtering, ticket changes, or release tracking.

How do I install this agent skill?

npx skills add https://github.com/cawcut/skill-cawplan --skill cawplan-my-work
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill facilitates the management of CawPlan tasks and tickets using a custom CLI. It presents a low risk of indirect prompt injection as it processes external data from ticket titles, comments, and links from the CawPlan API without using explicit boundary markers or sanitization.

  • Socketpass

    No alerts

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

CawPlan My Work

Bootstrap

cawplan skill check

Workflow

  1. Resolve your own user_id — this is decoded from your local access token, no network call needed:

    cawplan auth status
    

    Read the User ID: line from the output. If it's missing, re-authenticate (cawplan auth login, show the printed URL to the user, then cawplan auth login --device-auth --complete once they approve) rather than falling back to cawplan users query --email — that would spend a network call resolving something auth status should already have.

  2. Fetch your todos:

    cawplan todos user <user_id>
    

    This returns tickets (grouped by product_line → product → version), critical_issues (grouped by product_line → product), and summary. No status filter is applied by default — the response includes everything assigned to you, not just open items.

  3. If the user named a specific project/version, narrow tickets to that exact product → version leaf. critical_issues has no version dimension (only product_line → product), so it can't be narrowed to the same granularity — when the user named a version, narrow critical_issues to 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 in tickets, say so explicitly ("no tickets found for you under <name>") rather than falling back to showing everything.

  4. 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 response
    

    Exclude tickets whose status key maps to category COMPLETE or CANCELED. 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.

  5. 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 tickets across 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 sort CRITICAL → 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. Then fetch the candidates' status changes in bulk, at most 50 IDs per call:

cawplan tickets changes --unique_ids <candidate_ids_csv> --fields status --start_date <window_start> --end_date <window_end>

Every returned event is a real status change inside the window (at, old → new, new_category). Keep a Ticket only if it has at least one event. Do not use updated_at as final evidence. Report each Ticket once, using its latest in-window event; an unchanged Parent Ticket has no event and is excluded even if a child transition refreshed its record.

Fallback (only if tickets changes is unavailable, see references/QUERY_RESILIENCE.md): for every candidate, fetch cawplan tickets history <product_id> <version_id> <ticket_id> and keep a Ticket only if an UPDATED entry contains changed_fields.status (a new-status string or an {old, new} object) with created_at in the window. CREATED is not a status change.

  1. My reopened tickets (only when the user asks about reopened tickets / why something got reopened): there's no REOPENED status category (only UNSTARTED/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 every one of your tickets, regardless of current status, for any transition from a COMPLETE/CANCELED-category status back to a non-terminal category — each such transition is a reopen event. Fetch them in bulk (at most 50 IDs per call; default window is the last 90 days — say so, and add earlier 90-day windows only if the user asks about older reopens):
      cawplan tickets changes --unique_ids <ticket_ids_csv> --fields status --old_status_categories COMPLETE,CANCELED --new_status_categories BACKLOG,UNSTARTED,STARTED,TESTING --start_date <today-89d> --end_date <today>
      
      Every returned event is a reopen. CawPlan edits record the previous status (old / old_category); where an older record or a sync event lacks it, the server fills it from the ticket's preceding status change, even one before the window (old_source: previous_change). A change with no determinable previous status (no earlier change recorded) is not returned by this filter; if the user asks about one specific ticket, re-run without the two category filters and read its events in order. Fallback (only if tickets changes is unavailable): cawplan tickets history <product_id> <version_id> <ticket_id> per ticket. A ticket can have more than one reopen; 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 its display_name — if so you can call it out as "reopened" by name in the report; if not (e.g. it went straight back to in_progress or TESTING), 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_comment and 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 the change lookup fails for a ticket, list it as "not checked" (a partial result, see references/QUERY_RESILIENCE.md), not as "no reopen found" and not as evidence of a missing reason.
  2. 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 in references/CAWPLAN_OPEN_API.md under "VersionTicket fields of note") — todos/poll don't return this field, only the full ticket record does, so this step uses tickets search instead of steps 1-6's todos call.

    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 1
    

    Default <date>-<date> to today for both --updated_start_date/--updated_end_date unless 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 against uid.core-product's DAO, see references/CAWPLAN_OPEN_API.md), so a ticket created last week that you're actively working on today would be silently missed. --start_date/--end_date still has to be passed (the endpoint requires a created_at window or --time_range) — pin it to the maximal-window workaround (2000-01-01 to today) so it doesn't itself narrow the result. platform on a link isn't a reliable fixed value — the same manually-added GitHub link can show up as platform: "LINK" — so classify by the url itself: contains /pull/ → PR, contains /commit/ → commit, otherwise report it as a plain link with its title. A ticket with an empty links array has no repo links; say so rather than omitting it from the report. Page through using the response's total/page_num/page_size fields (keep fetching while page_num * page_size < total) rather than assuming one page of 100 covers everything.

  3. 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_ids in 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 links has a url containing /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.

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 summary if the response includes one and step 3 didn't narrow the scope — summary describes 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 any lookup, page or batch could not be completed, say what was verified and what was not before the list (references/QUERY_RESILIENCE.md). Never show CLI commands or raw errors.
  • 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
  • references/QUERY_RESILIENCE.md

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/cawcut/skill-cawplan/cawplan-my-work">View cawplan-my-work on skillZs</a>