Commit e81c570
fix: report-incomplete fails pipeline, percent-encode user_id, stage-1 status validation, merge_strategy validation, dead code removal (#141)
* feat: add 8 new safe output tools
Implements the remaining safe output features from GitHub issues #72-#79:
- add-pr-comment (#72): Create comment threads on Azure DevOps pull requests
with support for general and file-specific inline comments
- link-work-items (#73): Create relationships between work items (parent/child,
related, predecessor/successor, duplicate)
- queue-build (#74): Trigger Azure DevOps pipeline/build runs with optional
branch and template parameters
- create-git-tag (#75): Create annotated git tags on commits in ADO repositories
- add-build-tag (#76): Add tags to Azure DevOps builds for classification
- create-branch (#77): Create new branches without immediately creating a PR
- update-pr (#78): Update PR metadata (reviewers, labels, auto-complete, vote,
description)
- upload-attachment (#79): Upload file attachments to work items
Each tool includes:
- Params struct with validation
- Config struct for front matter configuration
- Executor with full ADO REST API implementation
- Sanitize impl for security
- Comprehensive unit tests
All 8 tools are registered in the MCP server, Stage 2 executor dispatch,
budget system, and write-permissions validation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address PR review feedback
Bug fixes:
- create-git-tag: resolve HEAD via repository's defaultBranch instead of
hardcoding 'heads/main' (works with master, develop, etc.)
- update-pr: resolve reviewer emails to GUIDs via VSSPS identity API
before adding to PR (ADO reviewers endpoint requires user ID, not email)
Security:
- update-pr: require 'allowed-votes' to be explicitly configured for vote
operation — empty list now rejects all votes to prevent accidental
auto-approve by agents
Improvements:
- update-pr: make auto-complete merge options configurable via front matter
(delete-source-branch, merge-strategy) instead of hardcoding squash+delete
- add-pr-comment: validate file_path in Validate::validate() at Stage 1
(was only validated at Stage 2, giving no feedback to agent)
- queue-build: sanitize template parameter keys and values to prevent
##vso[] command injection in build logs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: align with gh-aw — add review tools and enhancements
Adds 4 new safe output tools to align with gh-aw's PR review capabilities:
- submit-pr-review: Submit PR review with decision (approve, request-changes,
comment) and optional body/rationale text. Requires allowed-events config.
- reply-to-pr-review-comment: Reply to existing review comment threads
- resolve-pr-review-thread: Resolve/reactivate review threads (fixed, wont-fix,
closed, by-design, active)
- report-incomplete: Signal task could not complete due to infrastructure failure
Enhancements to existing tools:
- add-pr-comment: Add start_line param for multi-line code comments (gh-aw parity)
- link-work-items: Set DEFAULT_MAX=5 (matches gh-aw link-sub-issue default)
- queue-build: Set DEFAULT_MAX=3 (prevents pipeline queue flooding)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address second round of PR review feedback
Bug fixes:
- update-pr: derive connectiondata URL from org_url instead of hardcoding
dev.azure.com — supports vanity domains and national cloud endpoints
- update-pr: derive VSSPS identity URL from org_url instead of hardcoding
vssps.dev.azure.com — same environment portability fix
- submit-pr-review: same connectiondata URL fix (derived from org_url)
Security:
- upload-attachment: add canonicalize() + prefix check after resolving file
path to prevent symlink escape attacks (symlinks within workspace could
previously be followed to read arbitrary files outside source_directory)
Improvements:
- add-pr-comment: sanitize structural fields (repository, status, file_path)
with control-char stripping for defense-in-depth consistency
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: branch wildcard matching + VSSPS URL warning
- queue-build: drop equality arm from release/* wildcard matching so bare
'release' no longer matches 'release/*' — only 'release/...' does
- update-pr: add warn! log when VSSPS URL derivation produces no change
(surfaces the issue for visualstudio.com-hosted orgs at runtime)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: status mapping, VSSPS rejection, branch sanitize, policy order
Bug fix:
- add-pr-comment: fix WontFix status mapped to 6 (should be 3). Unify status
strings to kebab-case (active, fixed, wont-fix, closed, by-design) with
CamelCase accepted for backwards compatibility.
Security:
- update-pr: reject add-reviewers for non-dev.azure.com org URLs instead of
silently proceeding with a malformed VSSPS URL (*.visualstudio.com orgs)
Improvements:
- queue-build: sanitize branch field for defense-in-depth consistency
- update-pr: document allow-list semantics asymmetry (operations=permissive,
votes=secure) in UpdatePrConfig doc comment
- create-branch: check config policy (allowed-repositories) before resolving
repo alias, so operators see a policy error not a checkout-list error
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: repo policy ordering, VSSPS loop hoist, dedup resolve_repo_name
Bug fixes:
- create-git-tag: check config allowed-repositories before resolving repo
alias (same fix as create-branch — policy error before resolution error)
- update-pr: hoist VSSPS URL derivation and validation out of the
per-reviewer loop (avoids repeated work, fails fast before any API calls)
Refactor:
- Extract resolve_repo_name() to tools/mod.rs — was duplicated identically
in update_pr.rs and submit_pr_review.rs
Documentation:
- add-pr-comment: clarify start_line must be strictly less than line
- reply-to-pr-comment: explain parentCommentId=1 targets root comment
- upload-attachment: document ##vso[] scan UTF-8 boundary behavior
- mcp.rs: log warning on report-incomplete write failure
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address PR review feedback — report-incomplete, percent-encode user_id, status validation, merge_strategy validation, dead code removal
Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/474893c9-505a-48fb-a77e-768710027c85
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
* fix: improve merge_strategy tests to be non-tautological
Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/474893c9-505a-48fb-a77e-768710027c85
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
* fix: merge_strategy guard before GET, per-component .. check, compile-time submit-pr-review validation
Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/c36b2130-22bf-49ac-929f-0de6cada3ef6
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
* fix: review thread status 4→1, case-insensitive allowed_statuses, compile-time update-pr vote validation
Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/147051a9-a11a-4967-9c19-9fd9a2093064
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
* fix: flush NDJSON file after write to prevent stale reads
tokio::fs::File::write_all may buffer data internally without
flushing to the filesystem. Under load (e.g., full test suite),
a subsequent read_to_string could see stale data, causing
write_safe_output_file_with_maximum to miss already-written
entries and exceed the configured limit.
Adding an explicit flush() ensures data reaches the filesystem
before the function returns.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address 3 critical security issues from review
1. Self-approval guard for submit-pr-review and update-pr vote:
Both voting paths now fetch the PR createdBy.id and block positive
votes (approve, approve-with-suggestions) when the authenticated
identity is the PR author.
2. ##vso[ pipeline command neutralization in core sanitize():
Added neutralize_pipeline_commands() step that wraps ##vso[ and ##[
sequences in backticks, preventing ADO from interpreting them as
logging commands. This provides defense-in-depth for all text fields
across all safe output tools.
3. resolve-pr-review-thread fail-closed allowed-statuses:
Changed from permissive default (empty = all allowed) to fail-closed
(empty = all rejected). Added compile-time validator
validate_resolve_pr_thread_statuses() that requires explicit
allowed-statuses config, matching the pattern of submit-pr-review
allowed-events and update-pr allowed-votes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address 7 high-severity issues from review
4. link-work-items: Added required target config field (reuses
CommentTarget enum from comment-on-work-item). Execution now
fails if target is not configured, preventing unrestricted
cross-project work item linking.
5. queue-build: Added ADO variable injection check for template
parameter values. Rejects values containing \$(, \${{ or \$[
syntax that could reference pipeline variables.
6. upload-attachment: Fixed path traversal via backslash by
splitting on both / and \\ in .., .git, and absolute path
checks. Added tests for backslash-based traversal.
7. create-git-tag + create-branch: Added comprehensive git ref
name validation via shared validate_git_ref_name() helper.
Rejects .., @{, ~, ^, :, ?, *, [, \\, //, .lock suffix,
leading dots in path components, and trailing dots.
8. add-build-tag: Added allow-any-build config (default: false).
When not explicitly enabled, only the current pipeline build
(BUILD_BUILDID) can be tagged.
9. update-pr: Changed auto-complete to use the agent's own
identity from _apis/connectiondata instead of the PR
createdBy.id, providing correct audit attribution.
10. report-incomplete: Added sanitize_fields() call before using
the reason field in execute.rs to prevent injection via
unsanitized agent output.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: component-wise .. check in add_pr_comment, remove spurious pending status, use resolve_repo_name helper
Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/91091a0b-42a6-4559-afa4-44d12b847a4e
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>1 parent bc5e074 commit e81c570
21 files changed
Lines changed: 7131 additions & 7 deletions
File tree
- src
- compile
- tools
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
678 | 678 | | |
679 | 679 | | |
680 | 680 | | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
681 | 692 | | |
682 | 693 | | |
683 | 694 | | |
| |||
759 | 770 | | |
760 | 771 | | |
761 | 772 | | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
762 | 885 | | |
763 | 886 | | |
764 | 887 | | |
| |||
1350 | 1473 | | |
1351 | 1474 | | |
1352 | 1475 | | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
| 1485 | + | |
| 1486 | + | |
| 1487 | + | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
1353 | 1639 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
| 28 | + | |
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| |||
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
142 | 149 | | |
143 | 150 | | |
144 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
130 | 131 | | |
131 | 132 | | |
132 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
133 | 140 | | |
134 | 141 | | |
135 | 142 | | |
| |||
0 commit comments