# 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.

- **Type:** Skill
- **Install:** `agentstack add skill-jjw013-tech-debt-skill-tech-debt-tickets`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [jjw013](https://agentstack.voostack.com/s/jjw013)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [jjw013](https://github.com/jjw013)
- **Source:** https://github.com/jjw013/tech-debt-skill/tree/main/skills/tech-debt-tickets

## Install

```sh
agentstack add skill-jjw013-tech-debt-skill-tech-debt-tickets
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 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-skills` router.

Do NOT use this skill when:
- `findings.md` does not exist or doesn't conform to the schema — run `tech-debt-audit` first.
- The user wants fixes applied — use `tech-debt-fix` instead.

## 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 `/findings.md`. Confirm.
- **Output directory** — default `/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_version` is `"1.0"`.
- [ ] `summary.total_findings` equals 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:

1. If the user passed an explicit template path, use it.
2. If `/ticket-template.md` exists, use it. Announce: *"Using user template at `./ticket-template.md`."*
3. Otherwise, use the pack's default `templates/ticket.template.md`. Announce: *"Using default template (pack). To customize, drop a `ticket-template.md` at 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:

1. Extract the structured YAML block.
2. Extract the three markdown sections (Description, Rationale, Suggested fix) — the text content after each `**Section**` header, up to the next `##` or `**Section**` boundary.
3. Compute derived placeholders:
   - `{{location}}`: if `file` present with `line` → `:`. If `file` only → ``. If `scope: repository` → `(repository-wide)`.
   - `{{tags}}`: the YAML list rendered as a comma-separated string.
   - `{{title}}`: everything in the heading after `TD-NNN: `.
4. Substitute every `{{placeholder}}` in the template with the corresponding value. Unknown placeholders become empty strings — emit a warning for each so typos surface.
5. Apply the technical-writer persona's translation rules:
   - If the `description` reads like a finding (evidence-focused, engineer-for-engineer), rewrite it to be stakeholder-aware — but preserve the engineering detail in `suggested_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.
6. Write to `/--.md` where `slug` is 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 include `secrets` / `committed-credentials`), the ticket must include a rotation-and-history-purge section regardless of template — the template's `suggested_fix` placeholder 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: 
Output directory: 
Template used: >

By severity:
  critical:   → [list of IDs]
  high:     
  medium:   
  low:      

Warnings:
  
  
```

### 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:
1. Ask for the specific system and project/repo target.
2. Ask for credentials path or environment variable name. Do NOT accept credentials pasted into the chat.
3. 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.
4. 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.
5. Log each successful post and failure to `/push-log.md`.
6. 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: true` findings 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 `--.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.md` exists 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.md` override. Generic markdown output; API push is opt-in per invocation.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [jjw013](https://github.com/jjw013)
- **Source:** [jjw013/tech-debt-skill](https://github.com/jjw013/tech-debt-skill)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jjw013-tech-debt-skill-tech-debt-tickets
- Seller: https://agentstack.voostack.com/s/jjw013
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
