| name | new-ticket |
| description | Create a new ticket from scratch — intake backend first, mirror downstream after |
| risk_class | hard |
| confirm_action | new-ticket.create |
New Ticket
Create a brand-new ticket for something just found or thought of (bug, small
feature, improvement, admin task). Unlike /push, which lifts an existing
wiki page into an external backend, /new-ticket originates the work — it
creates the intake-side ticket, ingests the resulting page into the wiki,
and optionally mirrors to a downstream backend.
When to invoke
Trigger on any of:
/new-ticket
/new-ticket "<title> — <one-line description>"
- "new ticket for "
- "create a ticket to "
- "file a bug about "
Arguments
$ARGUMENTS — optional seed text. If present and substantive, parse into a
title and description. If empty or too terse, gather them in Step 2.
Behavior
Step 1 — Check intake config
Run via Bash:
rubber-ducky workspace intake show --json
The response either has a populated intake block (proceed to Step 2) or
null (run the first-run setup below).
First-run setup (one question at a time, with progress markers):
Run rubber-ducky backend list --json to see configured backends, so the
questions can offer real choices. If no backends are configured, stop:
"No backends are configured yet. Run /connect <name> first — I need at
least one to know where new tickets should land."
Then ask, one question per turn, prefixing each with its position so the
user knows the commitment up front:
Question 1 of 3. Where should new tickets originate? Pick one of your
configured backends: .
Question 2 of 3. What's the project / board / repo identifier in
where intake lands? (e.g., an Asana project GID, a Jira
project key, a GitHub owner/repo.)
Question 3 of 3. Should new tickets also be mirrored into a second
backend after intake (e.g., Asana → Jira)? If yes, name the backend; if
not, say "no". (If yes, I'll ask for the mirror project in a follow-up.)
If the user answers "yes" to Q3, ask one more turn:
Follow-up. What's the project / repo identifier in ?
Persist after each answer so a mid-flow abort doesn't lose progress:
rubber-ducky workspace intake set --primary-backend <name> --primary-project <id>
rubber-ducky workspace intake set --mirror-to <name> --mirror-project <id>
(Or --clear-mirror if the user later wants to drop mirroring.)
Once the intake block is populated, proceed to Step 2.
Step 2 — Capture title and description
If $ARGUMENTS is substantive, parse it into a title and a description and
confirm the title back to the user: "Title: <title>. OK?" Apply any
edits.
Otherwise, prompt one question at a time:
Question 1 of 2. What's the title? (Keep it tight — a TODO-style line,
not a sentence.)
Question 2 of 2. Quick description — what's the bug or the work? (One
or two lines is fine; I'll expand as needed in the draft.)
Step 3 — Optional context
If the workspace has tag conventions or label sets the user routinely picks
between (read wiki/references/ and UBIQUITOUS_LANGUAGE.md for any
"controlled vocabulary" hints), ask one short follow-up to cover them.
Otherwise skip. Don't interview — every additional question is friction the
user has to repeat for every new ticket.
Step 4 — Draft via ticket-writer
Invoke the ticket-writer sub-agent against intake.primary_backend:
Agent({
subagent_type: "ticket-writer",
prompt: "Draft a <primary_backend> ticket. Source: inline self-authored. Title: <title>. Body: <description>. Created via /new-ticket on <today>."
})
Walk the user through any NEEDS_INPUT placeholders the agent emits, one at
a time. The "ship it" shortcut accepts all defaults.
Step 5 — Show the write preview
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NEW TICKET PREVIEW — <primary_backend>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Target: <primary_backend> / <primary_project>
Assignee: me
Status: <initial status>
Title: <title>
Description:
------------
<body>
------------
After creation:
→ Ingest as wiki task page
→ Offer to mirror to <mirror_to> (if configured)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Confirm? (yes / no / edit)
Nothing is written before the user says yes.
Step 6 — Create the wiki page locally, then push via the gated CLI
/new-ticket reverses the historical "create externally first, ingest
second" flow: instead it creates the wiki task page locally and then
calls rubber-ducky push to externalize it. This means the external
create rides on the existing push gate — one CLI-enforced primitive,
zero new write paths.
-
Create the wiki page locally (no external write yet):
rubber-ducky page create task "<title>"
The page lands at wiki/tasks/<slug>.md with the description and
any tags / priority you elicited in Steps 2–3 set in frontmatter.
-
Issue a confirm-token for the push. The descriptor is
<primary_backend>.push so per-action overrides in
settings.confirm.<primary_backend>.push apply:
TOKEN=$(rubber-ducky --no-json confirm request \
--action <primary_backend>.push \
--preview "$PREVIEW_TEXT")
-
Push — consumes the token, calls the backend, stamps
<primary_backend>_ref / pushed / updated, audit-logs:
rubber-ducky --json push wiki/tasks/<slug>.md \
--backend <primary_backend> \
--confirm-token "$TOKEN"
A missing / expired / action-mismatched token causes push to exit
non-zero before any external call.
Capture the new ticket's identifier and URL from push's JSON output
(ref, url).
Backends with intake-form automations: some workspaces have
Smartsheet or similar tooling that rewrites fields after creation
(status reset, identifier assignment). If the user's intake involves
that, expect a brief delay and a possible field override; mention it
in the confirmation summary so the user isn't surprised, and offer a
follow-up update_tasks call manually if the override is the wrong
shape.
Step 7 — Offer to mirror (if mirror_to is configured)
If intake.mirror_to is set in workspace.md, ask:
Mirror to <mirror_to> now? (yes / no / later)
If mirror_to is unset, skip this step entirely.
Step 8 — Summary audit log
push already appended its own [write-back] push → ... line. Add a
summary that names this as a /new-ticket invocation so future
investigation can find it via grep:
rubber-ducky log append "[new-ticket] <primary_backend> (<ref>) — created via /new-ticket; mirror: <yes/no/later/none>"
Step 9 — Redirect to active task
Read active_task on today's daily page; if set, end with a one-liner
pointing back. Otherwise omit.
Rules
- Nothing is written to any external system before Step 5 confirmation.
The intake-creation, wiki ingest, and mirror push each get their own
confirmation (Steps 5 and 8) — but Step 5's yes covers both intake-create
and wiki-ingest, since they're inseparable.
- Primary intake always comes first. Never bypass to the mirror backend.
If the user explicitly insists ("just push to Jira directly"), push back
once: "This workspace's pattern is
<primary>-first. Want me to create
there and mirror after, or override?" If they override, honor it and log
the exception in log.md.
- If the primary-backend create fails, stop. Don't create the wiki page
without the backing — that's the exact drift this skill is designed to
prevent.
- First-run setup persists incrementally. Each answered question is
saved before the next is asked. Mid-flow abort is safe.
- Re-run is idempotent.
/new-ticket reads intake config fresh every
time; if the user wants to reconfigure intake, point them at
rubber-ducky workspace intake set (or /connect <backend> for credential
changes).
Output
A short confirmation line naming the created ticket, the wiki page path,
and the mirror outcome. Optional one-line redirect to the active task.