Skip to content

update-jira-ticket: skip HTML sanitization when a markdown/ADF tool (editJiraIssue) is available #709

Description

@williamthorsen

Problem

The update-jira-ticket skill fires for Claude and marches it down a full HTML-sanitization path — author HTML against an allowlist, run the deterministic pre-flight checker (update-jira-ticket.mjs) — even though Claude's available tool is editJiraIssue, which takes Markdown directly and has no HTML surface at all. The observed cost is repeated wasted work: content gets sanitized as the skill directs, only for Markdown (not HTML) to be what the tool actually wanted.

The skill's core machinery — the element allowlist, the composition rules, the pre-flight checker — exists solely to neutralize INVALID_INPUT errors from Jira's HTML→ADF conversion. When the available tool accepts contentFormat: "markdown" | "adf", that converter is never invoked, so the entire HTML path is a category error: the failure classes the checker guards against cannot arise.

Context

Two distinct Jira-update tool shapes exist in the wild:

  • HTML-based: update_jira_issue / create_jira_issue with description_html / comment_html. The conversion to ADF is where the known INVALID_INPUT triggers (code-mark nesting, multi-line <pre>, named entities, Confluence constructs) arise.
  • Markdown/ADF-based: editJiraIssue (Atlassian Rovo) with fields.description + contentFormat: "markdown" | "adf". Markdown is the simplified, safe path; ADF is full-fidelity JSON but verbose and harder to author.

The skill is a two-artifact bundle: hand-authored prose (SKILL.md) plus a generated helper (update-jira-ticket.mjs, an esbuild bundle of src/update-jira-ticket/). The checker and its src/ tree govern only the HTML path, so this change is confined to SKILL.md — no checker or source changes. The skill was originally written around the single HTML surface and encoded that one environment's constraint as the path; the fix is a decision gate that routes to the correct branch.

Proposed solution

Restructure SKILL.md around a decision gate, retaining the existing HTML content in substance:

  • Open with a tool-identification gate that names both shapes and states how to determine which is available (inspect the available MCP tools; prefer the contentFormat tool when both are present).
  • Add a short Markdown branch: author Markdown, pass via contentFormat: "markdown", prefer a local Markdown artefact when one exists. State a clear preference for Markdown over ADF, reserving ADF for fidelity Markdown cannot express. Explicitly state that the HTML allowlist, composition rules, and pre-flight checker do not apply, and that the checker must not be run.
  • Retain the existing HTML path as the other branch, reframed from "the one correct path" to the correct path for the HTML-surface tool. Its sub-sections nest under the branch (demoted a heading level) so the gated guidance no longer reads as universal.
  • Correct the frontmatter description so it names both tool shapes and scopes the pre-flight checker to the HTML branch, instead of implying the HTML surface is universal.

Acceptance criteria

Must have

  • The skill opens with a decision gate that names both Jira-update tool shapes and states how to determine which is available.
  • When a contentFormat-based tool (e.g. editJiraIssue) is available, the skill instructs authoring in Markdown (preferred) or ADF, and explicitly states the HTML allowlist, composition rules, and pre-flight checker do not apply.
  • The skill states a clear preference for Markdown over ADF on the contentFormat path.
  • The existing HTML allowlist + pre-flight checker path is retained for the description_html tool, reframed as one branch of the gate.
  • The frontmatter description names both tool shapes and scopes the pre-flight checker to the HTML branch.

Metadata

Metadata

Labels

featureAdded or improved external functionalityscope:agents

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions