plugins/avanti/skills/ticket/SKILL.md
Draft a new plan-scoped ticket from the avanti template into project/tickets/open/
npx skillsauth add acostanzo/quickstop ticketInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are the /avanti:ticket orchestrator. When the user runs /avanti:ticket <slug> --plan <plan-slug>, mint the next plan-scoped ticket ID, copy templates/ticket.md into project/tickets/open/<id>-<slug>.md, fill the frontmatter, and update the plan's tickets: array to include the new ID. Every ticket belongs to a plan — invocation without --plan is an error.
Read ${CLAUDE_PLUGIN_ROOT}/references/sdlc-conventions.md if you are uncertain about any lifecycle, ID-mint, or frontmatter rule.
$ARGUMENTS takes the form <slug> --plan <plan-slug>. Extract:
<id>- in the filename).--plan.If --plan is missing or has no value, abort:
/avanti:ticket requires a --plan <plan-slug> argument.
Every ticket belongs to a plan; there are no standalone tickets.
Usage: /avanti:ticket <slug> --plan <plan-slug>
Validate SLUG and PLAN_SLUG against ^[a-z][a-z0-9]*(-[a-z0-9]+)*$. On failure, use AskUserQuestion to re-prompt for whichever is invalid.
Run git rev-parse --show-toplevel 2>/dev/null. Abort if this fails. Store as REPO_ROOT.
Glob for project/plans/*/${PLAN_SLUG}.md under REPO_ROOT. If zero matches, abort:
No plan with slug "${PLAN_SLUG}" found under project/plans/.
Check the slug or draft the plan first with /avanti:plan ${PLAN_SLUG}.
If multiple match (should never happen per collision rules in /avanti:plan), abort and list all matches for the user to resolve.
Store the single matching path as PLAN_PATH.
The destination is deterministic: ${REPO_ROOT}/project/tickets/open/. If it is missing, create it with mkdir -p via Bash and continue. The destination is avanti's to manage and cheap to create on demand.
A repo with no project/ at all will already have failed the plan-resolve step in Step 3 (no plans means no --plan resolution), so this branch is unreachable in practice; if it is somehow reached, still proceed with the mkdir and write the ticket.
Read PLAN_PATH. Extract the tickets: array from the YAML frontmatter block.
tickets: key → treat as empty array [].tickets: is present but empty ([]) → starting fresh.tickets: holds [t1, t2, …] → use those.Parse the integer suffix from each entry that matches ^t\d+$ (e.g., t3 → 3). Ignore entries that do not match — plans commonly carry acceptance-bar IDs (a1, a2, …) in the same tickets: array, and those are not minted by this skill. Store the max of the t-prefixed IDs as MAX_ID (default 0 if no matching entries exist).
NEW_ID = t${MAX_ID + 1}.
Glob for project/tickets/*/${NEW_ID}-*.md under REPO_ROOT. For every match, read the file's frontmatter and check whether plan: equals PLAN_SLUG. Only abort if a same-plan match exists — different plans legitimately each have their own t1, t2, … sequence, so a t1-foo.md under another plan is not a collision. If a same-plan match is found, abort: "Ticket id ${NEW_ID} is already in use by <path> under plan ${PLAN_SLUG}." (Cross-plan IDs sharing the same numeric prefix are by design — see references/sdlc-conventions.md#plan-scoped-ticket-ids.)
Also glob for project/tickets/*/*-${SLUG}.md. Slug uniqueness is repo-wide because filenames don't carry the plan slug — two plans both choosing the slug foo would produce filename collisions. If any match, warn the user clearly and abort:
A ticket with slug "${SLUG}" already exists at <path>.
Pick a different slug.
Read ${CLAUDE_PLUGIN_ROOT}/templates/ticket.md as TEMPLATE. Run date +%Y-%m-%d as TODAY.
Use AskUserQuestion to collect:
Store as TITLE and CONTEXT.
Produce RENDERED by applying these substitutions to TEMPLATE:
id: TODO → id: ${NEW_ID}plan: TODO → plan: ${PLAN_SLUG}updated: TODO → updated: ${TODAY}# TODO — <ticket title> → # ${NEW_ID} — ${TITLE}## Context → ${CONTEXT}project/plans/active/<plan-slug>.md in the Links block → project/plans/active/${PLAN_SLUG}.md (leave as-is if the plan lives in draft/ or done/ — the convention is to reference the active path; stale links are rare and not worth guarding)Leave the acceptance-criteria, notes, and other TODO sections intact for the author to fill in.
Write RENDERED to ${REPO_ROOT}/project/tickets/open/${NEW_ID}-${SLUG}.md.
Use Edit on PLAN_PATH to add NEW_ID to the tickets: array in the plan's frontmatter.
tickets: holds [t1, t2, t3] → rewrite to [t1, t2, t3, ${NEW_ID}].tickets: is empty [] → rewrite to [${NEW_ID}].tickets: key → add one immediately after status:.Also bump the plan's updated: to TODAY — any new ticket is a meaningful plan-level change.
Tell the user:
Ticket drafted: project/tickets/open/${NEW_ID}-${SLUG}.md
Plan updated: ${PLAN_PATH} (tickets: […, ${NEW_ID}])
Next:
- Fill in the acceptance criteria and any notes.
- Move to in-progress by editing status (folder stays put).
- Close with /avanti:promote ticket:${NEW_ID}-${SLUG} when done.
--plan missing: abort immediately with the "every ticket belongs to a plan" message. Never fall through to a default plan./avanti:plan.*-${SLUG}.md): abort with the existing path.tickets: and updated:), then re-raise.documentation
Surface (and optionally fix) doc-tree drift — duplicates, dead links, stale docs, template non-compliance, missing `## Related` blocks. Read-only by default; `--apply` does mechanical fixes; `--apply-semantic` emits diffs for human review.
documentation
Full-text search over the repo's `docs/` tree (FTS5-backed). Returns ranked hits with file paths, tags, and matching snippets.
testing
Retrieval-augmented Q&A over the repo's `docs/` tree. Returns a one-paragraph synthesis plus citations (doc path + heading anchor) and per-citation corroboration verdicts. Field shape and ordering are locked at M3; M5 populates the verdicts.
documentation
Scaffold a new doc under `docs/` from a Diátaxis template, or update an existing one and bump its `updated:` date. Suggests `## Related` candidates and refreshes the FTS5 index on write.