一键导入
tickets-batch
File 5–20 structured tickets in one flow — shared-context Qs once, 3-Q micro-interview per ticket, then per-ticket `tracker_create` (gh/glab/custom).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
File 5–20 structured tickets in one flow — shared-context Qs once, 3-Q micro-interview per ticket, then per-ticket `tracker_create` (gh/glab/custom).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Review a PR for quality, security, and standards compliance. Invokes the Code Reviewer agent (Rex).
Review a technical design / migration AgDR / feature spec for architectural soundness BEFORE the Build phase. Invokes the Solution Architect agent (Tariq) — the non-code analog of /code-review.
Score a review agent (Rex/Hakim/Tariq) against a labeled PR corpus — ground-truth defect-set overlap, never a prose rubric. Headline metric is approve-precision.
Security-focused PR review for vulnerabilities and best practices. Invokes the Security Reviewer agent (Shield).
Record per-PR design-review approval (UI merge gate). ONLY on an explicit per-PR designer "approved".
Record per-PR CEO approval and merge in one turn. ONLY on an explicit per-PR "approved" — never on umbrella "go".
| name | tickets-batch |
| description | File 5–20 structured tickets in one flow — shared-context Qs once, 3-Q micro-interview per ticket, then per-ticket `tracker_create` (gh/glab/custom). |
| argument-hint | <optional bulk description> |
| allowed-tools | Bash, Read, Write |
The fast happy path for filing 5–20 tickets in one intent (project kickoff, roadmap decomposition, handover integration plan). Use this instead of raw gh issue create (non-conformant) or running /feature / /task / /bug N times serially (~10 questions × N tickets).
This skill is the fast happy path. Each ticket it produces conforms to the project's .ticket.required_sections schema by construction — never by post-hoc validation. The matching validate-issue-structure.sh hook is a backstop, not the primary fix.
Flow shape:
/tickets-batch
→ 1 shared-context Q batch (priority, epic, area-labels, repo)
→ N micro-interviews (≤ 3 Qs each: type, one-line purpose, optional clarification)
→ 1 confirmation
→ N `tracker_create` calls (one per ticket — never a single batch dump)
Read the registry path via portfolio_registry, the per-project docs dir via portfolio_projects_dir, and the ideas backlog via portfolio_ideas_backlog — all from .claude/hooks/_lib-portfolio-paths.sh. Source the helper at the top of any bash block that touches those paths:
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-read-config.sh"
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-portfolio-paths.sh"
registry=$(portfolio_registry)
Defaults match today's single-fork layout (./apexyard.projects.yaml, ./projects, ./projects/ideas-backlog.md). Adopters in split-portfolio mode override the portfolio.{registry, projects_dir, ideas_backlog} keys in .claude/project-config.json. Don't hardcode literal apexyard.projects.yaml or projects/ paths in bash blocks — the helper resolves whichever mode the adopter is in. See docs/multi-project.md.
/tickets-batch
/tickets-batch File 12 tickets for the auth refactor
/tickets-batch ./backlog-batches/handover-integration.md
The argument is free-form — a description, a markdown file path, or empty. Step 2 below normalises whatever you pass into a list of titles.
Read .claude/session/current-ticket to determine which repo we're working in. If absent:
apexyard.projects.yaml for managed projects.Which project is this batch for?owner/repo format.Confirm the resolved repo with the user before continuing — a wrong repo means N misfiled tickets, hard to undo.
Accept ANY of these input shapes:
a) A list pasted in one message — numbered or bulleted, one title per line:
1. Wire OIDC discovery endpoint
2. Add session refresh to token middleware
3. Migrate user table to new auth schema
- Sweep deprecated /v1/login routes
- Add audit log for failed login attempts
b) A path to a markdown file containing the same — detect when $ARGUMENTS is a single token ending in .md or starts with ./ / / and points at an existing file.
c) Empty / a free-form description — ask:
Paste the list of titles, one per line, or give me a file path to read from.
Strip list markers (1., -, *, •, leading whitespace). Drop empty lines and lines starting with # (treated as comments / headings). The result is an ordered list of N titles.
Cap: if N > 20, stop and say:
That's {N} tickets — over the per-batch cap of 20. Split into batches of ≤ 20
and re-run /tickets-batch for each. (The cap exists to keep the confirmation
step reviewable; bumping it later is a config change, not a skill rewrite.)
If N < 2, suggest /feature / /task / /bug instead — this skill is overkill for a single ticket.
Ask conversationally, one question at a time, but only once for the entire batch — not per ticket:
a) Default priority
Read the priority scheme from .claude/project-config.json → .ticket.label_priority_scheme (fallback P0,P1,P2,P3). Present the values:
Default priority for this batch?
1. P0 — must-have for current milestone
2. P1 — ship soon
3. P2 — future
4. P3 — backlog
(Per-ticket overrides aren't asked — bulk-file flow trades per-ticket priority for speed.
Re-prioritise after filing if needed.)
b) Optional epic / parent ticket
Optional epic or parent issue to reference in every ticket body?
(e.g. #42, owner/repo#42, or Enter to skip)
If provided, every filed ticket body gets a Refs <epic> line at the bottom. If skipped, no parent reference is added.
c) Optional area labels
Area labels to apply to all tickets? (comma-separated, e.g. area-backend, area-auth)
(Or Enter to skip. Type-specific labels — enhancement, bug, etc. — are auto-applied per ticket.)
Validate that each label is a single token (no spaces). If a label looks risky (e.g. contains priority — would conflict with the priority label), warn and re-ask.
d) Repo confirmation
Echo the resolved repo and the count, and confirm before starting the per-ticket interviews:
Filing {N} tickets to {owner/repo}, default priority {P1}, area labels: {labels or "none"},
parent: {epic or "none"}.
Continue? (yes / change / cancel)
For each title in order, run a maximum-3-question micro-interview. Show progress: [Ticket 3 of 12].
Q1 — Type (always asked):
Read the whitelist from .claude/project-config.json → .ticket.prefix_whitelist (fallback Feature, Bug, Chore, Refactor, Testing, CI, Docs). Present numbered options:
[Ticket 3 of 12] "Migrate user table to new auth schema"
Type?
1. Feature — user-facing capability
2. Bug — broken behaviour
3. Chore — tech debt / housekeeping
4. Refactor — restructure without behaviour change
5. Testing — test coverage / fixtures
6. CI — pipelines / tooling
7. Docs — documentation
Accept the number or the type name (case-insensitive).
Q2 — One-line purpose (always asked):
One sentence on what this ticket does and why.
(Used to infer the body — User Story / Driver / Given-When-Then.)
Loop until non-empty. From the type + purpose, infer a draft body that conforms by construction to .ticket.required_sections[<type>]:
| Type | Required sections (from schema) | Inferred body shape |
|---|---|---|
| Feature | User Story, Acceptance Criteria | Restructure purpose into "As a [persona], I want [goal] so that [benefit]." If persona is unclear, default to "user". Acceptance Criteria starts with one checkbox derived from the purpose, plus a - [ ] TBD placeholder. |
| Chore | Driver, Scope, Acceptance Criteria | Driver = the "why" half of the purpose. Scope = the "what" half (or TBD if not separable). Acceptance Criteria = one checkbox + - [ ] TBD. |
| Refactor | Driver, Scope, Acceptance Criteria | Same as Chore. |
| Testing | Driver, Scope, Acceptance Criteria | Same as Chore. |
| CI | Driver, Scope, Acceptance Criteria | Same as Chore. |
| Docs | Driver, Acceptance Criteria | Driver = the purpose. Acceptance Criteria = one checkbox + - [ ] TBD. |
| Bug | Given / When / Then, Repro | Given/When/Then inferred from the purpose: Given = current state, When = trigger, Then = broken behaviour. If can't infer, set placeholder lines. Repro = - [ ] TBD: add repro steps. |
Every section must be non-empty — empty sections fail validate-issue-structure.sh. Always emit a placeholder (TBD: <hint>) rather than an empty header.
Q3 — Optional clarification (asked ONLY if inference is low-confidence):
Inference is low-confidence when:
In those cases, ask one targeted question:
| Missing | Question |
|---|---|
| Feature persona/benefit | Who's it for and what do they get out of it? |
| Bug trigger | What action triggers the bug? |
| Chore why | Why is this needed — what breaks or degrades if we don't do it? |
| Chore what | What specifically changes — files, services, behaviour? |
If inference is confident, skip Q3 and move on.
After Q1–Q3, show the inferred body inline (compact form, 4–6 lines) and continue to the next ticket without asking for confirmation per ticket — full-batch confirmation happens at step 5.
Display all N tickets in a compact table:
Batch summary — {N} tickets to {owner/repo}:
| # | Type | Title | Priority | Labels |
|----|----------|----------------------------------------------------|----------|-------------------------|
| 1 | Feature | Wire OIDC discovery endpoint | P1 | enhancement, area-auth |
| 2 | Feature | Add session refresh to token middleware | P1 | enhancement, area-auth |
| 3 | Chore | Migrate user table to new auth schema | P1 | area-auth |
| ...
| 12 | Testing | Add OIDC integration tests | P1 | area-auth |
Parent: #42
Confirm? (yes = file all / edit N = re-interview ticket N / cancel = abort)
Handle the response:
yes → proceed to step 6edit N (e.g. edit 3) → jump back to step 4 for that ticket only, then re-show the summarycancel / no → abort, no tickets filed, no state writtenDo not file any ticket before this confirmation. Partial commits-before-confirm are forbidden — a misclick at the summary should leave the tracker untouched.
For each ticket in order, run a specific tracker_create call — one call per ticket, NEVER a single bulk JSON dump. The validator runs per-issue, so per-issue calls are the only conformant shape. Dispatch through tracker_create (#670 / AgDR-0072, extended by the #709 creator sweep) so the tickets land in this project's tracker — GitHub, GitLab, or a custom CLI. For a GitHub adopter each call runs gh issue create exactly as before.
Build the title as [<Type>] <title>. Build the body from the inferred sections, ending with the optional Refs <epic> line if a parent was set.
# Resolve + source the tracker lib ONCE, before the loop, by walking up from cwd.
tracker_lib="$(r="$PWD"; while [ -n "$r" ] && [ "$r" != / ]; do \
[ -f "$r/.claude/hooks/_lib-tracker.sh" ] && { echo "$r/.claude/hooks/_lib-tracker.sh"; break; }; \
r="${r%/*}"; done)"
# shellcheck source=/dev/null
. "$tracker_lib"
# ── per ticket ──────────────────────────────────────────────────────────────
body_file="$(mktemp)"
cat > "$body_file" <<'BODY'
{formatted body}
BODY
# tracker_create <owner/repo> <title> <body_file> [<labels_csv>] → {"ref","url"}.
result="$(tracker_create "{owner/repo}" "[{Type}] {title}" "$body_file" "{type-label},{priority},{area-labels}")"
rc=$?
rm -f "$body_file"
# rc=3 → tracker.kind=none (shape-only); rc!=0/empty → hard failure (see step 7).
ref="$(printf '%s' "$result" | jq -r '.ref // empty')" # e.g. 451 — used in the progress line
Type-label mapping:
| Type | Auto-applied label |
|---|---|
| Feature | enhancement |
| Bug | bug |
| Chore / Refactor / Testing / CI / Docs | (none — type is in title prefix; labels stay area + priority) |
Show progress per call, using the ${ref} parsed from each tracker_create:
[1/12] Filing "Wire OIDC discovery endpoint"… → owner/repo#451 ✓
[2/12] Filing "Add session refresh to token middleware"… → owner/repo#452 ✓
On the first tracker_create failure (rc non-zero or empty result), stop the batch immediately. Do not silently skip. (A tracker.kind=none project returns rc=3 with the rendered body on stdout — treat that as "shape-only, nothing filed" and stop the batch the same way, telling the operator to file the set in their external system.) Show:
[5/12] Filing "Migrate user table to new auth schema"… ✗
Error from the tracker CLI / validator:
{stderr — usually the validator's "missing section: Driver" line}
Filed so far: 4 tickets ({owner/repo}#451, #452, #453, #454).
Remaining: 8 tickets (not filed).
What now?
1. Retry — re-run the same tracker_create call (use this if the failure was transient)
2. Skip — drop this ticket, continue with the next 7
3. Edit — re-interview this ticket and retry
4. Abort — stop here; the 4 already-filed tickets stay (no rollback)
Do not roll back already-filed tickets on abort. Tell the user exactly which ones did file — they can close the unwanted ones manually if they choose, but silent rollback would be worse than partial completion.
One line per created ticket:
Filed {N}/{total} tickets to {owner/repo}:
#451 — Feature — Wire OIDC discovery endpoint — https://github.com/{owner}/{repo}/issues/451
#452 — Feature — Add session refresh to token middleware — https://github.com/{owner}/{repo}/issues/452
#453 — Chore — Migrate user table to new auth schema — https://github.com/{owner}/{repo}/issues/453
...
Skipped / failed: 0
Next: prioritise with the team, then `/start-ticket <N>` to begin work.
If any tickets were skipped or failed, list them under a separate Skipped / failed: section with the failure reason for each.
These are the exact shapes the inferred bodies must take. Each section header must be non-empty (placeholders allowed) so validate-issue-structure.sh passes.
## User Story
As a {persona}, I want {goal} so that {benefit}.
## Acceptance Criteria
- [ ] {criterion derived from the purpose}
- [ ] TBD — refine before starting work
{Refs <epic> if set}
## Driver
{why this is needed — derived from the purpose}
## Scope
{what changes — derived from the purpose, or "TBD: define before starting work"}
## Acceptance Criteria
- [ ] {criterion derived from the purpose}
- [ ] TBD — refine before starting work
{Refs <epic> if set}
## Driver
{why these docs are needed — derived from the purpose}
## Acceptance Criteria
- [ ] {criterion derived from the purpose}
- [ ] TBD — refine before starting work
{Refs <epic> if set}
## Given / When / Then
**Given** {precondition derived from purpose, or "TBD"}
**When** {trigger derived from purpose, or "TBD"}
**Then** {broken behaviour derived from purpose, or "TBD"}
## Repro
- [ ] TBD: add concrete repro steps
{Refs <epic> if set}
.ticket.required_sections by construction. Never produce a body that the validate-issue-structure.sh hook would reject. Every required section is present and non-empty (placeholders allowed); section headers match the schema spelling exactly.tracker_create per ticket. NEVER a single batch-mode JSON dump — the validator runs per-issue and a bulk shape silently bypasses it. (For a GitHub adopter each call is a gh issue create.)cancel at the summary leaves the tracker untouched.argument-hint: "<optional bulk description>" — accept a free-form description, a markdown file path, or empty input. Normalise to a list of titles in step 2..ticket.prefix_whitelist, .ticket.label_priority_scheme, and .ticket.required_sections from .claude/project-config.json (with defaults from .claude/project-config.defaults.json). Don't hard-code the schema in the skill — config drives.me2resh/apexyard), never let a ticket title or body reference a registered private project name. The block-private-refs-in-public-repos.sh hook will reject such calls; the skill's job is to not produce them in the first place.gh issue edit directly or open a follow-up.TBD: …), say so in the summary table — don't pretend the body is complete. The user can edit N to refine before filing.Part of ApexYard — multi-project SDLC framework for Claude Code · MIT.