Tech debt tickets
Converts a findings.md (produced by tech-debt-audit) into one ticket markdown file per finding. Supports a user-supplied ticket-template.md override at the project root. After writing files, offers to push tickets to a ticketing API (Jira, GitHub, GitLab, Linear) — but never pushes without explicit consent.From its SKILL.md
npx -y skills add jjw013/tech-debt-skill --skill tech-debt-ticketsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
10.3 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
Tech Debt Tickets
Overview
This skill reads a findings.md produced by tech-debt-audit and writes one ticket markdown file per finding into a tech-debt-tickets/ directory. Each ticket is paste-ready for Jira, GitHub Issues, GitLab, or Linear; the format is determined by either the user's custom template (ticket-template.md at the project root) or the pack's default.
After all tickets are written, the skill asks whether the user wants to push them to a ticketing API. It does NOT push automatically. Pushing involves a separate, explicit confirmation per target system.
When to Use
Trigger on any of:
- User chose "tickets" after the audit finished (path 1 from the audit skill summary).
- User directly invokes this skill pointing at an existing
findings.md. - User has picked this skill explicitly from the
using-tech-debt-skillsrouter.
Do NOT use this skill when:
findings.mddoes not exist or doesn't conform to the schema — runtech-debt-auditfirst.- The user wants fixes applied — use
tech-debt-fixinstead.
Persona Adopted
This skill adopts the technical-writer persona defined at agents/technical-writer/SKILL.md. Read that file before proceeding.
If the harness supports sub-agents: delegate the rendering + rephrasing work to a sub-agent prompted with the technical-writer persona. The parent composes the final summary and handles the API-push prompt.
If the harness does not support sub-agents: assume the technical-writer persona directly.
The persona's rules are binding:
- Never copy the finding description verbatim — translate for audience.
- Always produce checkable acceptance criteria.
- Redaction is permanent — never fill in what the audit redacted.
- Never push to external systems without explicit per-invocation consent.
Process
1. Confirm inputs with the user
Ask (or accept from the prior skill's handoff):
- Findings file path — default
<repo>/findings.md. Confirm. - Output directory — default
<repo>/tech-debt-tickets/. Confirm. If the directory already contains files, ask whether to overwrite or abort. - Template choice — see step 3.
2. Validate findings.md against schema
Read findings.md. Validate against templates/findings.schema.md §4 rules:
- Has top-level YAML frontmatter.
-
schema_versionis"1.0". -
summary.total_findingsequals the count of## TD-headings. - Every finding has a valid YAML block with required fields.
- Every finding has Description, Rationale, and Suggested fix sections.
If any check fails, abort with a clear message. Do not attempt to "fix" the findings file; the audit skill is authoritative for its own output.
3. Resolve the template
Look up the template in this order; first match wins:
- If the user passed an explicit template path, use it.
- If
<project_root>/ticket-template.mdexists, use it. Announce: "Using user template at./ticket-template.md." - Otherwise, use the pack's default
templates/ticket.template.md. Announce: "Using default template (pack). To customize, drop aticket-template.mdat your project root."
Read the template in full. Check it for {{placeholder}} names; warn the user if any placeholder isn't in the known list (see templates/ticket-template.example.md for the full list) — typos become empty strings in the output.
4. For each finding, render a ticket
Parse findings.md into individual findings. For each finding:
- Extract the structured YAML block.
- Extract the three markdown sections (Description, Rationale, Suggested fix) — the text content after each
**Section**header, up to the next##or**Section**boundary. - Compute derived placeholders:
{{location}}: iffilepresent withline→<file>:<line>. Iffileonly →<file>. Ifscope: repository→(repository-wide).{{tags}}: the YAML list rendered as a comma-separated string.{{title}}: everything in the heading afterTD-NNN:.
- Substitute every
{{placeholder}}in the template with the corresponding value. Unknown placeholders become empty strings — emit a warning for each so typos surface. - Apply the technical-writer persona's translation rules:
- If the
descriptionreads like a finding (evidence-focused, engineer-for-engineer), rewrite it to be stakeholder-aware — but preserve the engineering detail insuggested_fix. - If the template's acceptance criteria are template-generic (e.g., "suggested approach implemented"), supplement with finding-specific checkable items where possible. Only do this if the template includes an acceptance-criteria section.
- If the
- Write to
<output_dir>/<id>--<slug>.mdwhereslugis the title, lowercased, non-alphanumerics collapsed to-, trimmed to 50 chars.
5. Special handling for high-severity findings
If any finding has severity: critical:
- Prepend
[CRITICAL]to the ticket title. - If the finding is about a committed secret (
category: security+ tags includesecrets/committed-credentials), the ticket must include a rotation-and-history-purge section regardless of template — the template'ssuggested_fixplaceholder will likely already have this if the audit was done right, but double-check. If it's missing, flag to the user rather than silently proceed.
6. Produce the summary
Print a summary:
Tickets written: <count>
Output directory: <path>
Template used: <default | user-supplied at <path>>
By severity:
critical: <n> → [list of IDs]
high: <n>
medium: <n>
low: <n>
Warnings:
<any template placeholder warnings>
<any findings skipped for schema-validation reasons>
7. Offer API push — with explicit consent
Print:
Files are written. Do you want to push these tickets to a ticketing system?
1. No — I'll review locally and file manually (or never file).
2. Yes → which system? (Jira / GitHub Issues / GitLab / Linear / other)
3. Dry-run — show me the first API call you'd make for the first ticket, without sending.
If the user says yes:
- Ask for the specific system and project/repo target.
- Ask for credentials path or environment variable name. Do NOT accept credentials pasted into the chat.
- Verify a write-capable tool is available in the current harness (MCP server, API binding, gh CLI, etc.). If none is available, explain what's needed and stop.
- For each ticket, ask confirmation before the FIRST API call. After the first succeeds, ask whether to continue batch-posting the rest or prompt per ticket.
- Log each successful post and failure to
<output_dir>/push-log.md. - If any critical-severity ticket fails to post, stop the batch and surface it immediately.
Do NOT:
- Accept credentials in chat.
- Batch-push without the first-call confirmation.
- Retry failures silently.
Rationalizations
| Excuse | Rebuttal |
|---|---|
| "The user said 'generate tickets'; they obviously also want them pushed." | No. Writing files is one action. Calling an external API is another. The step 7 prompt is non-negotiable. |
| "This finding's description is already stakeholder-ready; I'll just copy it." | If it's truly ready, quick rewrite costs nothing; if it's not, skipping the rewrite is debt. Do the rewrite. |
| "Template doesn't have an acceptance-criteria section, so I'll make one up inside the suggested-approach." | If the user's template omits ACs, trust their choice — don't smuggle them in elsewhere. Ask if they want ACs elsewhere. |
"A placeholder {{foo}} is unknown; I'll treat it like a typo and delete it." | Don't delete. Substitute empty, warn. The user may have typed it intentionally as a literal; warnings let them see it. |
| "Two findings are really the same thing — I'll merge them into one ticket." | Don't. Findings have separate IDs for traceability. If you think they should be one ticket, say so in the summary and let the user decide; don't silently collapse. |
| "Critical finding about auth — let me file a Jira ticket right away without asking." | Especially never for critical findings. Auth issues often want a private issue (not the public repo's Issues tab), which is a human decision. |
| "The template's placeholder list is outdated for a new field I just added to findings.md." | The schema is authoritative. If you added a field to findings, update the template in the pack AND warn about gaps with user templates — don't bend the rendering in ways users can't see. |
Red Flags
Stop and reset if:
- You're about to push to an external system without an explicit per-push-batch confirmation.
- You're copying the finding's description verbatim into the ticket.
- The ticket title begins with "Fix" or "Improve" with no object.
- You're inventing acceptance criteria that aren't traceable to the finding.
- You notice a secret value somewhere in the rendered ticket — STOP, scrub the ticket, re-check every ticket in the batch.
- Tickets for
auto_fixable: truefindings get no distinction — the user may want the fix skill to handle those instead of filing tickets for them. - The output directory already has tickets and you're about to overwrite without asking.
Verification
The skill is done when ALL of these are true:
- All findings produced a ticket file OR were explicitly skipped with a reason in the summary.
- Each ticket filename follows
<id>--<slug>.md. - No secret values appear in any ticket file (grep pass before finishing).
- Summary has been shown to the user.
- The API-push prompt (step 7) was shown and the user responded.
- If push was declined, no external API calls were made.
- If push was accepted, per-system confirmation was captured AND the first-ticket confirmation happened before batching.
-
push-log.mdexists in the output directory if any push attempt happened.
If any item fails, fix it before reporting the skill complete.
Version History
- 1.0 (current) — Reads findings.md per schema v1.0. Supports user-supplied
ticket-template.mdoverride. Generic markdown output; API push is opt-in per invocation.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.