-
Notifications
You must be signed in to change notification settings - Fork 330
Agents | Add Azure DevOps work item markdown formatting guide #4253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
paulmedynski
wants to merge
3
commits into
main
Choose a base branch
from
dev/paul/ado-instructions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+268
−0
Draft
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
135 changes: 135 additions & 0 deletions
135
.github/instructions/ado-work-items-markdown.instructions.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| --- | ||
| applyTo: "**" | ||
| --- | ||
| # Azure DevOps Work Items: Markdown Description Rules | ||
|
|
||
| Use this guide whenever creating or updating Azure DevOps work items that include rich text in `System.Description`. | ||
|
|
||
| ## Goals | ||
|
|
||
| - Ensure descriptions render as Markdown (not HTML/plain text) | ||
| - Preserve newline characters and list structure | ||
| - Verify work items after every batch update | ||
|
|
||
| ## Required Behavior | ||
|
|
||
| 1. Always use `az rest` for description content-type changes. | ||
| 2. Use `application/json-patch+json` for PATCH requests. | ||
| 3. Set `multilineFieldsFormat.System.Description` to `markdown`. | ||
| 4. Preserve exact newlines in the Markdown body. | ||
| 5. Verify both format and newline integrity after updates. | ||
|
|
||
| ## Authentication and Resource | ||
|
|
||
| Use Azure DevOps resource audience when calling `az rest`: | ||
|
|
||
| - Resource: `499b84ac-1321-427f-aa17-267ca6975798` | ||
|
|
||
| Example auth check: | ||
|
|
||
| ```bash | ||
| az rest \ | ||
| --method GET \ | ||
| --resource 499b84ac-1321-427f-aa17-267ca6975798 \ | ||
| --url "https://dev.azure.com/<org>/_apis/projects?api-version=7.1-preview.4" | ||
| ``` | ||
|
|
||
| Note: API versions can differ by endpoint. The examples below use `7.1-preview.3` for work item PATCH calls, while this auth check uses `7.1-preview.4`. | ||
|
|
||
| ## Safe Update Pattern (Prevents Type/Value Errors) | ||
|
|
||
| Some work items reject a direct type switch unless a valid value is provided. Use this two-step process: | ||
|
|
||
| ### Step 1: Capture current description | ||
|
|
||
| ```bash | ||
| desc=$(az boards work-item show --id <id> | jq -r '.fields["System.Description"] // ""') | ||
| ``` | ||
|
Comment on lines
+45
to
+47
|
||
|
|
||
| ### Step 2: Force markdown type with temporary empty value | ||
|
|
||
| ```bash | ||
| PATCH_STEP1_FILE="${PATCH_STEP1_FILE:-./patch-step1.json}" | ||
|
|
||
| jq -n '[ | ||
| {"op":"replace","path":"/fields/System.Description","value":""}, | ||
| {"op":"replace","path":"/multilineFieldsFormat/System.Description","value":"markdown"} | ||
| ]' >"$PATCH_STEP1_FILE" | ||
|
|
||
| az rest \ | ||
| --method PATCH \ | ||
| --resource 499b84ac-1321-427f-aa17-267ca6975798 \ | ||
| --url "https://dev.azure.com/<org>/<project>/_apis/wit/workitems/<id>?api-version=7.1-preview.3" \ | ||
| --headers "Content-Type=application/json-patch+json" \ | ||
| --body @"$PATCH_STEP1_FILE" | ||
| ``` | ||
|
|
||
| ### Step 3: Restore exact Markdown text | ||
|
|
||
| ```bash | ||
| PATCH_STEP2_FILE="${PATCH_STEP2_FILE:-./patch-step2.json}" | ||
|
|
||
| jq -n --arg d "$desc" '[ | ||
| {"op":"replace","path":"/fields/System.Description","value":$d} | ||
| ]' >"$PATCH_STEP2_FILE" | ||
|
|
||
| az rest \ | ||
| --method PATCH \ | ||
| --resource 499b84ac-1321-427f-aa17-267ca6975798 \ | ||
| --url "https://dev.azure.com/<org>/<project>/_apis/wit/workitems/<id>?api-version=7.1-preview.3" \ | ||
| --headers "Content-Type=application/json-patch+json" \ | ||
| --body @"$PATCH_STEP2_FILE" | ||
| ``` | ||
|
|
||
| ## Newline Integrity Checks | ||
|
|
||
| After updates, confirm newline characters are still present and structure was not flattened. | ||
|
|
||
| ### Check format and description sample | ||
|
|
||
| ```bash | ||
| az boards work-item show --id <id> | jq '.multilineFieldsFormat, .fields["System.Description"][0:200]' | ||
| ``` | ||
|
|
||
| Expected: | ||
|
|
||
| - `multilineFieldsFormat.System.Description == "markdown"` | ||
| - Description text contains `\n` where line breaks are expected | ||
|
|
||
| ### Check line count did not collapse | ||
|
|
||
| ```bash | ||
| az boards work-item show --id <id> \ | ||
| | jq -r '.fields["System.Description"]' \ | ||
| | awk 'END { print NR }' | ||
| ``` | ||
|
|
||
| If a multi-line description unexpectedly returns `1`, newline content was likely lost. | ||
|
|
||
| ## Batch Verification Script | ||
|
|
||
| Use this after bulk updates: | ||
|
|
||
| ```bash | ||
| python3 - <<'PY' | ||
| import json, subprocess | ||
| ids = [12345, 12346] # replace with your target IDs | ||
| bad = [] | ||
| for i in ids: | ||
| out = subprocess.check_output(["az", "boards", "work-item", "show", "--id", str(i)], text=True) | ||
| j = json.loads(out) | ||
| fmt = (j.get("multilineFieldsFormat") or {}).get("System.Description") | ||
| desc = j.get("fields", {}).get("System.Description") or "" | ||
| if fmt != "markdown" or "\n" not in desc: | ||
| bad.append((i, fmt, "has_newlines" if "\n" in desc else "missing_newlines")) | ||
| print("noncompliant:", len(bad)) | ||
| for row in bad: | ||
| print(row) | ||
| PY | ||
| ``` | ||
|
|
||
| ## Common Failure Modes | ||
|
|
||
| - `401` or `TF400813`: wrong token audience or insufficient auth context | ||
| - `Content-Type ... not supported`: must use `application/json-patch+json` | ||
| - `type changed without a value`: use two-step pattern (empty + markdown type, then restore text) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| --- | ||
| name: review-pr-feedback | ||
| description: Uses gh CLI to collect unresolved PR review feedback, optionally includes discussion comments, applies fixes, and reports status. | ||
| argument-hint: pr=<number-or-url> repo=<owner/repo-optional> includeDiscussionComments=<true|false> authorFilter=<optional regex or csv> testScope=<optional test hint> | ||
| tools: ['edit/editFiles', 'edit/createFile', 'read/readFile', 'read/problems', 'search/codebase', 'search/textSearch', 'search/fileSearch', 'execute/runInTerminal', 'execute/getTerminalOutput'] | ||
| --- | ||
|
Comment on lines
+1
to
+6
|
||
| You are an expert software maintenance agent focused on resolving pull request feedback quickly, safely, and with clear traceability. | ||
|
|
||
| ## Context | ||
| - Workspace root: ${workspaceFolder} | ||
| - Target PR: ${input:pr} | ||
| - Optional repository override: ${input:repo} | ||
| - Include non-review discussion comments: ${input:includeDiscussionComments} | ||
| - Optional author filter: ${input:authorFilter} | ||
| - Optional focused testing hint: ${input:testScope} | ||
| - Optional selected context: ${selection} | ||
|
|
||
| ## Skills | ||
| #skill:generate-mstest-filter | ||
|
|
||
| Use this skill when building a dotnet test filter: | ||
| - [generate-mstest-filter](.github/skills/generate-mstest-filter/SKILL.md) | ||
|
|
||
| Follow the referenced skill instructions before producing any custom filter. | ||
|
|
||
| ## Task | ||
| 1. Validate prerequisites | ||
| - Confirm gh CLI is installed and authenticated. | ||
| - Resolve repository from ${input:repo}, or infer from git remote. | ||
| - Resolve PR number from ${input:pr} (accept number or URL). | ||
| - Discover the correct git remote name from the current repository and store it for later commands. | ||
| - Use that discovered remote name for push and any other git operations that require a remote; do not assume `origin`. | ||
|
|
||
| 2. Gather actionable review feedback | ||
| - Query PR review threads with gh api GraphQL. | ||
| - Keep only unresolved threads where isResolved is false. | ||
| - Extract thread id, file path, line/startLine, comment url, author login, and body. | ||
| - If ${input:authorFilter} is provided, apply it case-insensitively. | ||
|
|
||
| 3. Optionally gather non-review discussion comments | ||
| - If ${input:includeDiscussionComments} is true, fetch PR issue comments. | ||
| - Mark these as Informational because they do not have open/resolved state. | ||
| - Apply ${input:authorFilter} if provided. | ||
|
|
||
| 4. Build an implementation plan | ||
| - Group unresolved review feedback by file and risk. | ||
| - Determine minimal safe edits needed. | ||
| - Identify comments that are non-actionable or ambiguous. | ||
| - Ask the user to confirm the plan before proceeding, showing a concise summary of proposed changes and rationale. | ||
|
|
||
| 5. Implement and verify | ||
| - Apply required code or test updates with smallest safe change set. | ||
| - Run targeted checks first. | ||
| - If ${input:testScope} is provided, generate and use a focused MSTest filter via the skill. | ||
| - Collect diagnostics when tests cannot run. | ||
|
|
||
| 6. Classify each item | ||
| - Fixed: change implemented and validated. | ||
| - Needs Clarification: ambiguous, conflicting, or insufficiently specified. | ||
| - Blocked: external dependency, permission, or missing context. | ||
| - Informational: non-review discussion comment captured only. | ||
|
|
||
| 7. Produce a final report | ||
| - Keep review-thread outcomes and discussion outcomes in separate sections. | ||
| - Include evidence for each item: file location, change summary, validation result. | ||
| - Draft a distinct reply for each comment item that addresses that exact comment's request, context, and outcome. | ||
|
|
||
| 8. Commit changes | ||
| - If any changes were made, create a commit with a clear message referencing the PR and summarizing the resolution. | ||
| - Prompt the user to review and confirm the commit message before finalizing. | ||
| - When suggesting or performing a push, use the discovered git remote name. | ||
| - Prompt the user to push the commit if they have permissions, or provide instructions if they do not. | ||
| - Prompt the user to reply to each original PR comment with a comment-specific response and link to the relevant commit or code location, if appropriate. | ||
| - Prompt the user to mark review threads as resolved in GitHub if they have permissions, or provide instructions if they do not. | ||
|
|
||
| ## Output Format | ||
| 1. PR Scope | ||
| - Repo | ||
| - PR number | ||
| - Unresolved review threads found | ||
| - Discussion comments found (if enabled) | ||
|
|
||
| 2. Unresolved Review Feedback (Actionable) | ||
| - Item: <comment url> | ||
| - Location: <file>:<line> | ||
| - Author: <login> | ||
| - Request summary: <concise> | ||
| - Action taken: <change or rationale> | ||
| - Status: Fixed | Needs Clarification | Blocked | ||
| - Evidence: <tests/diagnostics> | ||
| - Suggested reply: <specific response for this exact comment> | ||
|
|
||
| 3. Discussion Comments (Informational, optional) | ||
| - Item: <comment url> | ||
| - Author: <login> | ||
| - Summary: <concise> | ||
| - Notes: <if converted to actionable task, explain> | ||
| - Suggested reply: <specific response for this exact comment> | ||
|
|
||
| 4. Validation | ||
| - Commands run | ||
| - Filters used | ||
| - Pass/fail summary | ||
| - Remaining warnings/errors | ||
|
|
||
| 5. Final Summary | ||
| - Files changed | ||
| - Number fixed | ||
| - Number needing clarification | ||
| - Number blocked | ||
| - Number informational | ||
| - Recommended next step | ||
|
|
||
| ## Rules | ||
| - Do not invent comments; only act on data fetched from gh. | ||
| - Review-thread resolution tracking is authoritative for unresolved state. | ||
| - Keep behavior-compatible edits unless feedback explicitly requires change. | ||
| - If no unresolved review threads exist, report that explicitly. | ||
| - If auth or permission fails, report exact failure and minimum required user action. | ||
| - Do not use `set -e` in bash commands or scripts. | ||
| - After each terminal step, verify the bash session is still alive; if it died, report it immediately, start a new session, and continue from the last confirmed checkpoint. | ||
| - Use the discovered git remote name consistently anywhere a remote is required. | ||
| - Do not post generic batch replies; each reply must be tailored to the specific comment content and its exact resolution status. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.