emit-tickets
Materialise a roadmap into an agents/tickets/{slug}/ bundle — one ticket per
buildable step — then wire the markers back and run the buildability gate.
When to use
| Signal | Match |
|---|---|
| "turn this roadmap into tickets" | yes |
| "materialise / emit tickets for <roadmap>" | yes |
| "mach Tickets aus der Roadmap" | yes |
| "plan the work for <roadmap>" | yes |
| User wants a YAML ticket bundle, not a prose plan | yes |
| Refining or splitting an existing ticket | no → use refine-ticket |
| Estimating a single ticket | no → use estimate-ticket |
Upstream: roadmap-writing — author the roadmap first.
Downstream: src/scripts/lint_ticket_buildable.ts (the build-readiness gate). A ticket reaches a tracker by paste or MCP (ADR-102) — no export script.
Procedure
Steps at a glance:
- Locate and parse the roadmap.
- Create
agents/tickets/{slug}/and draft one ticket YAML per materializable step. - Assign
model_tiervia the granularity floor; split oversized steps. - Compute SHA refs for
adr_refs/source_refs. - Write
manifest.ymlwith acyclicdependency_graphand emptylinear_state. - Append
<!-- ticket: T-NNN -->markers back into the roadmap. - (Re)generate
agents/tickets/_registry.yml. - Run
lint_ticket_buildableuntil exit 0 (max 3 attempts). - Tell the user the bundle is ready: paste a ticket into Linear/Jira, or have the agent create it via a tracker MCP server (ADR-102 — no API export).
§0 — Locate the roadmap
Confirm the roadmap slug and open agents/roadmaps/{slug}.md. Identify all
materializable steps (checkbox items that describe a code or docs change). Skip
informational steps, phase headings, and acceptance-criteria prose.
§1 — Derive the bundle slug
agents/tickets/{slug}/ — same slug as the roadmap. Create the directory.
§2 — One ticket per step
For each materializable step, draft a ticket YAML:
id: T-NNN
roadmap: {slug}
phase: {N}
title: "{step text, ≤80 chars}"
status: ready
model_tier: {lite | medium | high} # see §3
estimate: {story-points, integer}
priority: {1=critical … 4=low}
labels: []
parent: null
blocked_by: []
adr_refs: []
source_refs: []
assets: none
acceptance:
- "{measurable done criterion}"
boundaries:
must_touch: []
may_touch: []
must_not_touch: []
Use estimate-ticket, technical-specification, or refine-ticket when a
step needs deep estimation or spec work.
§3 — Assign model_tier by granularity floor
Apply this floor before marking any ticket lite:
| Criterion | Required for lite |
|---|---|
| Files touched | ≤ 5 |
| Lines changed | ≤ 200 |
| Isolation-testable | yes — no cross-module side effects |
- All three pass →
lite - Any miss → split the ticket further, or escalate to
medium - Architectural / multi-module →
high(useadr-createfirst)
Gate: run ./scripts-run src/scripts/lint_ticket_buildable.ts agents/tickets/{slug}/
and fix all errors before declaring any ticket lite. This is the only
authoritative check — do not skip it.
§4 — Compute SHA refs
For each adr_refs and source_refs entry:
git rev-parse HEAD:path/to/file
Fill the sha: field with the result, or pending for files not yet committed.
§5 — Write manifest.yml
bundle: {slug}
generated: {ISO-8601 date}
dependency_graph:
T-001: []
T-002: [T-001]
# … acyclic; no circular deps
linear_state: {} # always empty at emit time
Verify acyclicity by tracing every blocked_by chain — no ticket may appear
in its own transitive dependency set.
§6 — Write markers back into the roadmap
For each materializable step in agents/roadmaps/{slug}.md, append
<!-- ticket: T-NNN --> to the end of the step line:
- [ ] Add X to Y <!-- ticket: T-003 -->
One marker per step; do not duplicate on re-run (check before appending).
§7 — (Re)generate _registry.yml
Append or update the bundle entry in agents/tickets/_registry.yml:
bundles:
- slug: {slug}
path: agents/tickets/{slug}/
status: draft
ticket_count: {N}
If the file does not exist, create it with the bundles: root.
§8 — Run the buildability gate
./scripts-run src/scripts/lint_ticket_buildable.ts agents/tickets/{slug}/
Fix every reported error. Re-run until exit code 0. Max 3 attempts; if still failing, surface the linter output and ask for guidance.
§9 — Hand off (paste / MCP)
Tell the user:
Bundle written to
agents/tickets/{slug}/. Each ticket's body is paste-ready Markdown for a Linear/Jira issue; or create issues via a tracker MCP server. No API export (ADR-102).
Do NOT auto-create tracker issues — paste/MCP is the user's call.
Output format
agents/tickets/{slug}/manifest.yml— bundle manifest (acyclic graph, empty linear_state)agents/tickets/{slug}/T-NNN-{slug}.md— one file per ticket (YAML frontmatter)agents/tickets/_registry.yml— updated bundle registry- Inline
<!-- ticket: T-NNN -->markers in the source roadmap
Do NOT
- Implement or invent ticket content not traceable to a roadmap step.
- Touch
src/scripts/**— orchestrate; do not reimplement. - Mark a ticket
litebeforelint_ticket_buildablepasses. - Create a circular
dependency_graph— verify acyclicity before writing. - Auto-create tracker issues — paste/MCP is the user's call (ADR-102, no API export).
- Reuse T-NNN numbers from another bundle in the same registry.
Gotchas
- Re-run safety: before appending
<!-- ticket: T-NNN -->markers, grep for existing markers so a re-run does not duplicate them. - SHA = pending: new files not yet committed get
sha: pending; remind the user to re-run after commit to update SHAs. - Split signals: if a step touches > 5 files or > 200 lines, split it
into two tickets and add a
blocked_bydependency before continuing. - Format contract:
docs/contracts/ticket-bundle-format.mdis the authoritative schema;src/agent-src/templates/tickets.mdis the template.