Files
PowerToys/.github/scripts/pr-intake/README.md
Niels Laute e5a19c4ac5 fix(ci): correct issue and PR triage automation (#50052)
## Summary

- skip AI issue triage when the latest issue state is closed and recheck
state before publishing
- restrict duplicate searches and digest canonical candidates to live
open issues
- add deterministic, additive `Product-*` labels from changed paths for
draft and non-draft PRs
- map Window Hopper, Cursor Wrap, and all Mouse Jump project paths to
their specific product labels before generic fallbacks
- preserve manually applied product labels while managing only intake
lifecycle labels and trusted comments
- collect the PowerToys version and release channel in one required
bug/localization field
- add Window Hopper to the bug report area dropdown and preserve parsing
of both old and combined version headings

This consolidates and supersedes #49961 and #49804.

## Validation

- `node --test .github\scripts\pr-intake\tests\pr-intake.test.mjs` - 39
passing
- `python -m unittest discover .github\scripts\issue-triage\tests -v` -
55 passing
- parsed all modified issue-form and workflow YAML files with PyYAML
- verified every current `src/modules/*` root maps to a product label
- verified the Window Hopper path maps to `Product-Window Hopper`
- `git diff --check`

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b313a270-e6e8-4c4a-89b2-880c1d79027c
Copilot-Session: 498721d4-1098-4298-ac8a-147066fbfea3
2026-08-26 12:13:16 -07:00

2.5 KiB

Pull request intake

The workflow in .github/workflows/pr-intake.yml applies deterministic product labels to all pull requests and runs intake checks on non-draft pull requests. It does not call any AI model and does not execute any code from the pull request head; the Node script reads all pull request data through the GitHub API.

Flow

  1. Read the current PR and changed files through the GitHub API.
  2. Add recognized Product-* labels from the historical path mapping. The longest path prefix wins, generic Settings/General labels are suppressed when a more specific product matches, and existing product labels are never removed.
  3. Re-fetch mergeability a few times when GitHub still reports it as unknown so a conflicting PR is never treated as ready by default.
  4. Deterministically validate closing issue references, merge conflicts, and whether visual evidence is present.
  5. Require visual evidence only when the changed paths touch product UI files.
  6. Keep a single canonical comment in sync and manage the Ready for review and Needs-Author-Feedback lifecycle labels.

Product labeling is additive. Intake never removes an existing product label, and a pull request that touches multiple mapped roots receives each matching label. Draft pull requests receive product labels but skip readiness checks.

Comment behavior

  • If there is anything for the author to act on or consider, a single canonical comment is posted or updated.
  • If the PR is clean and a previous intake comment exists, it is replaced with a short all-clear note.
  • If the PR is clean and no intake comment exists, nothing is posted.

Missing issue references are advisory. Explicitly invalid references, merge conflicts, unknown mergeability, and missing required visual evidence block readiness. Draft PR events run deterministic path labeling, remove intake lifecycle labels, delete trusted canonical intake comments, and then stop. Marking a draft ready triggers full intake.

The existing resource-management policy closes PRs that retain Needs-Author-Feedback for seven inactive days. PR synchronization is handled by this workflow rather than the legacy policy responder.

Robustness limits

  • Closing references parsed from the untrusted PR body are capped (MAX_CLOSING_REFERENCES) and verified with bounded concurrency (CLOSING_VERIFY_CONCURRENCY) so a crafted body cannot exhaust the API rate limit.

Run the focused tests with:

node --test .github\scripts\pr-intake\tests\pr-intake.test.mjs