SuperAPI AI Directory

fix-ado-comment-markdown

Office & productivity

View repository

Updated 11-03 15:31

About this skill

Fix ADO Comment Markdown

Invocation (explicit invocation): This skill runs only when the user explicitly invokes it—in Claude Code use /fix-ado-comment-markdown, in Codex CLI use $fix-ado-comment-markdown; do not apply it automatically when it is not named.

This skill covers two things:Markdown posting/repair for ADO comments(flows A and B), anda general Markdown correction tool(section C, included).

The storage format of ADO comments is determined byeach comment's format field(markdown or html), not by the content.az boards work-item update --discussion and JSON Patch /fields/System.History are only stored as html; when several sentences are crammed into one paragraph, they stick together as one big block on ADO. Always post and modify comments through the Comments REST API and specify format=markdown, and correct the syntax with the included Markdown correction tool before sending.

The tools are all in this skill's directory:scripts/ado_comments.py(uses only the Python standard library, invoked via az rest ) and scripts/markdown-fixer.mjs(zero-dependency Node). Below, <skill> refers to this skill's directory (for example, ~/.agents/skills/fix-ado-comment-markdown),$T refers to <skill>/scripts/ado_comments.py,$MF refers to <skill>/scripts/markdown-fixer.mjs. Set up first:

export ADO_ORG=https://dev.azure.com/<org> ADO_PROJECT=<project>

Put drafts and manifests in a temporary or scratchpad directory, not in the project working tree.

ADO Markdown facts

  • API:POST .../_apis/wit/workItems/{id}/comments?format=markdown&api-version=7.1-preview.4 adds;PATCH .../comments/{commentId}?format=markdown&api-version=7.1-preview.4 modifies; the body is always {"text": "<markdown>"}。format is a required query parameter.
  • Existing html comments can be PATCHed directly to markdown:version plus 1, and the UI shows "edited".
  • When read back, renderedText is returned only when adding $expand=renderedText .
  • #12345 renders as a work item link.Bare URLs do not automatically become links: write the URL as [文字](URL) or <URL>。
  • Tables,##/### headings, numbered and bulleted lists, bold, and inline code all render normally; table cells cannot contain unescaped |。
  • To also change state or assignment, do it in two steps: first use az boards work-item update to change the fields (without --discussion), then post the Markdown comment.
  • Multi-line fields (Description, Repro Steps, etc.) are a different mechanism: JSON Patch adds /multilineFieldsFormat/<欄位> = Markdown, and after saving it cannot be changed back to HTML. This skill does not handle fields unless the user explicitly asks.

A. Post a new comment

  1. Write the draft: write the content as comment.md. Structure first: a one-sentence title, tables for comparison data (URLs, versions, Tasks, Commits), numbered lists for steps, bulleted lists for results; put backticks around SHAs and paths; write URLs as [文字](URL)。 Done condition: each paragraph has at most one topic, and there are no consecutive long paragraphs of more than two sentences.
  2. Correct:node $MF --check comment.md, then node $MF --write --ignore-rule MDX018 comment.md, and rerun --check. MDX070 (bare URLs) must be changed to links; MDX018 (first heading is not H1) can be ignored for comments. Done condition: --check only MDX018 remains, or 0 issues.
  3. Post:python3 -I $T post --id <workItemId> --file comment.md。 Done condition: output format is markdown,renderedLength greater than 0.

B. Repair existing HTML comments

  1. Inventory:python3 -I $T pull --id <ID> [<ID> ...] --author <uniqueName> --out <dir>. By default only fetch format=html;--format '' to fetch all. For each, output <wi>-<cid>.orig.txt(original text),<wi>-<cid>.md(draft), and manifest.json(including version and work item status). Whole-project repair: When the user requests the entire project, WIQL cannot find comment authors, so first inventory candidate work items, then use pull --author to filter comments:
    az boards query --wiql "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @project ORDER BY [System.Id]" --query "workItems[].id" -o tsv
    
    When there are many IDs, batch them (about 50 per batch)pull to their respective <dir>, and complete steps 2–6 for each batch; do not stuff all project IDs into a single batch. Completion criteria: The number of comments listed matches the scope specified by the user; comments outside the scope have been removed from the manifest.
  2. Reorganize drafts: The tool-generated .md is only a starting point (splitting sentences at periods/semicolons, bolding leading labels, adding backticks around SHAs). Reorganize each one against .orig.txt : turn comparable data into tables and steps into numbered lists. Only re-layout the text; do not change the meaning or add/remove facts. Common mechanical conversion errors: bold text cut off, ";" inside parentheses split into two items, 8-digit dates mistaken for SHAs, long labels not recognized. Completion criteria: Every draft has been read through and compared with the original text, and every fact from the original is still present.
  3. Correct:node $MF --check <dir>, then for the confirmed files node $MF --write --ignore-rule MDX018 <files>, rerun --check; convert bare URLs to links. Completion criteria: Only MDX018 remains, or 0 issues.
  4. Dry run:python3 -I $T apply --manifest <dir>/manifest.json --dry-run. It rereads each comment; ifversion or format differs from the inventory, skip it; skip when the work item is Done/Removed/Closed, and add only when the user explicitly names it --include-closed。 Completion criteria: Each one is dry-run or has an explained skip。
  5. Write: remove --dry-run and run again (you can use --only <commentId ...> to try one first). Results are written to <dir>/apply-results.json。 Completion criteria: For each, result is ok、newFormat is markdown。
  6. Spot-check rendering:python3 -I $T verify --id <ID> --comment <commentId>, confirm renderedTags contains the expected table/ol/ul/strong; if needed, add --show to view the HTML. Completion criteria: Spot-check at least one of each layout type (table type, list type), and the rendering matches expectations; report to the user the number processed, number skipped, and reasons.

Security boundaries

  • Only modify comments within the user-specified scope and by the specified author; do not touch others' comments.
  • Whole-project repair involves a large number of changes: first --dry-run and report the total number of comments and batches, and write only after user confirmation.
  • Modifying a comment shows "edited" in ADO; before rewriting handoff comments the other party has already read, explain the impact first.
  • Done/Removed/Closed items are not modified by default; add only when the user names them --include-closed。
  • Credentials and tokens are obtained only via az , and are not written to drafts, the manifest, or output.

C. Markdown correction tool (markdown-fixer.mjs)

A zero-dependency Node script (requires Node.js 20 or later; 22+ recommended) that divides common Markdown syntax errors into two categories: formatting issues that can be fixed automatically, and structural or semantic issues that require human judgment. The workflow is: check first, then write only to explicitly specified files, review the diff, and finally re-run to confirm.

Quick Start

# 檢查(預設模式;不帶路徑時掃描目前目錄)
node $MF --check README.md docs/

# 只寫入明確指定的檔案
node $MF --write README.md docs/guide.md

# 只看某幾條規則
node $MF --check --rule MDX010,MDX011 README.md

# 忽略某條規則
node $MF --check --ignore-rule MDX032 docs/

# CI 用的 JSON
node $MF --check --json docs/

# 列出規則
node $MF --list-rules
  • --check is the default mode and does not write files.
  • --write An explicit path is required; if a directory is given, it processes all Markdown files scanned under that directory. First run --check to see the list; if no path is provided, it will refuse outright to avoid accidentally rewriting the entire working tree.
  • Exit codes:0 no issues require processing;1 warnings/errors remain (with --strict , info also counts);2 usage, I/O, or parsing error.
  • --rule MDX090 automatically enables a 120-character line length; you can also use --max-line-length N to specify it.
  • --json 's changed indicates that the write actually happened this time,wouldChange indicates that the file needs changes; in check mode, changed is always false。

Workflow

  1. Define the scope. List the Markdown files to be processed this time; excluding vendor/、node_modules/, generated files, and golden fixtures. Completion criteria: There is a clear list of files, and you know which files will not be touched.

  2. Check first, do not write first. Run --checkon the list, recording rule IDs, line numbers, and severity. Completion criteria: You can distinguish which are fixable, which are report-only, and which are structural errors.

  3. Assess the risk. If MDX081 (unclosed frontmatter), MDX083 (unclosed HTML comment), MDX053 (invalid fence info), or MDX085 (unclosed $$ math block) appears, fix the structure manually first; do not expect --write to handle it. Completion criteria: There are no structural errors that would cause the tool to refuse to write.

  4. Write only to explicit files. Use --write <files>, one scope at a time. Do not use --write .。 Completion criteria: The command finishes, and no files outside the list were written.

  5. Review the diff. Run git diff -- <files>, and confirm section by section. Pay special attention to headings, list boundaries, table column counts, and CJK line length. Completion criteria: Every diff can be explained as to why it was changed; unwanted changes have been excluded with --ignore-rule or manually reverted.

  6. Handle report-only items manually. Fix according to the description in reference/rules.md , or explicitly accept with --ignore-rule . Completion criteria: Every remaining warning/error has a rationale for how it was handled.

  7. Re-run verification. Run --checkagain; the goal is 0 warnings/0 errors, or only info with a documented rationale. Completion criteria: The command exit code is 0, or the remaining items have been clearly explained.

  8. Finish according to project conventions. If these are changes to be committed, follow AGENTS.md to update the version number and run the corresponding tests. Completion condition: The checks required by the project and the version number update are both completed.

Safety contract

  • Only change Markdown syntax, not meaning, not wording, not paragraph re-layout.
  • Do not touch fenced code, inline code, frontmatter, math expressions, URLs, raw HTML, link destinations. Two trailing spaces are treated as an intentional line break and will be preserved.
  • Do not invent image alt text, link targets, heading levels, or table content.
  • Leave uncertain places for human judgment; report-only rules will not be --write applied.
  • MDX081、MDX083、MDX053、MDX085, and the case where "the fix would turn --- into frontmatter" will leave the file unchanged and report the reason; this is a deliberate safety refusal, not a bug. Blocking rules, even if named by --ignore-rule , will not be allowed to write.
  • This tool is a line-oriented heuristic checker, not a full CommonMark parser. Multi-line inline structures, MDX/JSX, and complex YAML will not be fully parsed.

Automatically fixable rules

Rule Content
MDX001 Remove the UTF-8 BOM at the start of the file
MDX002 Normalize CRLF/CR to LF
MDX003 Keep exactly one newline at the end of the file
MDX004 Remove trailing whitespace; preserve hard breaks with two spaces
MDX005 Collapse multiple consecutive blank lines into one
MDX006 Remove blank lines at the start of the file
MDX008 Replace NBSP outside code/URL with a normal space
MDX010 #Title → # Title
MDX011 Keep only one space after the heading marker
MDX012 Remove trailing ###
MDX013 Add a blank line between a heading and an adjacent paragraph
MDX020 blockquote's > keep only one space after; preserve indented code
MDX030 -item → - item、1.item → 1. item
MDX031 Lists at the same indentation level use the same bullet type
MDX040 Remove **、__、*、_ extra whitespace on the inside (single */_ only fix asymmetric cases)
MDX052 Add a blank line between top-level fenced code and adjacent blocks
MDX060 Each cell of the table delimiter row has at least three -
MDX062 Add a blank line between top-level tables and adjacent blocks
MDX082 Add one blank line after frontmatter

These fixes still need to be reviewed in the diff.MDX010 cannot distinguish #hashtag from a broken heading;MDX030 cannot distinguish -item from an English word starting with a hyphen;MDX031 may unify two lists separated by a blank line into the same marker.

Report-only rules that are not auto-fixed

  • Headings and structure: MDX014 indented heading, MDX015 skipped level, MDX016 empty heading, MDX017 trailing punctuation in heading, MDX018 first heading is not H1, MDX019 multiple H1s, MDX080 Setext ambiguity, MDX081 unclosed frontmatter, MDX083 unclosed HTML comment, MDX084 full-width Markdown syntax, MDX085 unclosed $$ math block.
  • Lists and emphasis: MDX032 missing blank line between list and paragraph, MDX035 empty list item, MDX041 possibly unmatched emphasis markers.
  • Code fence: MDX050 missing language, MDX051 unclosed fence, MDX053 invalid fence info.
  • Tables: MDX061 inconsistent column count, MDX063 code/URL inside a table cell contains an unescaped |。
  • Links and images: MDX070 bare URL, MDX071 empty link, MDX072 ] ( spaces, MDX073 missing reference definition, MDX074 duplicate definition, MDX075 image missing alt.
  • Other: MDX007 tab, MDX009 zero-width character, MDX090 line length.

Full documentation, before/after examples, approximate markdownlint mapping, and CJK considerations are in reference/rules.md。

Common operations

# 只修標題相關
node $MF --write --rule MDX010,MDX011,MDX012,MDX013 README.md

# 先看某個目錄有多少問題,不要寫入
node $MF --check docs/

# 把 info 也視為失敗,適合嚴格 CI
node $MF --check --strict docs/

# 只看前幾行問題
node $MF --check docs/ | head -40

Paste-to-Markdown project notes

  • This tool processesthe Markdown documents in the project, not the app's paste conversion logic. Runtime conversion is in assets/clipboard2markdown.js and assets/to-markdown.js; to change paste behavior, you must change the app logic and add e2e/ tests; running this script alone is not enough.
  • tests/tcN-perfect.md are golden fixtures and represent the app's expected output. Unless the conversion behavior is intentionally changed, do not run --writeon them; if the conversion behavior really is changed, update the fixtures together with the corresponding E2E expectations.
  • Do not run --write .in that repo. It will scan AGENTS.md、tasks/todo.md and the golden fixtures, producing unnecessary diffs.
  • Any change to be committed must follow AGENTS.md:index.html 's footer and JSON-LD softwareVersion to bump the patch version in sync; the cache-busting query string only needs updating when JS/CSS is changed.
  • This script's own tests:
    node --test <skill>/scripts/markdown-fixer.test.mjs
    

Known limitations

  • Frontmatter must start at the first byte of the file (a BOM may be present).--- If there is a blank line before it, it is semantically a thematic break; if removing the blank line would make the first line (ignoring BOM) become ---, the tool refuses to write even if that line might just be a thematic break; please confirm manually.
  • HTML blocks use an approximation of CommonMark type 1–7 detection. Types 6/7 continue until the next blank line, so when there is no blank line after </div> , the following Markdown is treated as raw HTML and not processed.
  • Tables indented 4 or more space columns (tabs count as 4 columns), and tables inside blockquotes, may not be detected; tables indented 1–3 spaces inside lists are detected, but MDX062 does not handle them.
  • Indented paragraph continuation (lazy continuation) and indented code boundaries are determined heuristically; a line indented 4 or more columns that immediately follows a paragraph is treated as paragraph continuation.
  • Files starting with --- and containing a second --- are always treated as frontmatter; if it is actually a Setext heading or horizontal rule, confirm manually first. If removing the leading blank line would turn the following --- into frontmatter,--write refuses to write.
  • Directory scanning skips .git、node_modules、vendor、coverage、test-results、playwright-report、blob-report、.e2e-tmpby default; other hidden directories (for example .github、.agents) are still scanned.
  • Line length is counted in Unicode code points, with CJK counted as 1, not terminal display width; table rows are not counted in MDX090.
  • Multi-line links/emphasis, headings and lists inside nested blockquotes, and complex YAML are not fully parsed.
  • A multi-line math block starts with $$ at the start of a line, blockquote, list, or task-list content, and ends at any subsequent line containing $$ ; if the block content itself contains $$ , it ends early. A leading $$ is always treated as the start of a math block; if it is just text, please rewrite it or add a backslash. A multi-line single $...$ is not supported;```math is still protected by fenced code. Deeper mixed nesting (for example, a blockquote inside a list and then another list) may not match precisely, and MDX085 will be reported conservatively;\[...\]、\begin{...} and other math syntaxes are not specially protected either.
  • MDX002 When disabled, if there are no other fixes, the file remains unchanged (including mixed line endings); if there are other fixes, line endings are normalized with CRLF first, then CR.
  • NBSP in URLs is only reported, not automatically changed; please manually replace it with %20 or fix the URL.