Files
PowerToys/.github/aw
Niels Laute 662346fab0 Improve issue triage product-label detection (#49905)
## Summary

Issues that put the module in a `[Module]` title prefix (a common
PowerToys convention) but omit the bug template's **"Area(s) with
issue?"** section were left **Unclassified** with no `Product-*` label —
e.g. #49899 *"[Screen Ruler] Settings crashes ..."* got no
`Product-Screen Ruler` label despite the title.

Root cause: product-label detection was purely deterministic and narrow.
`parse_area` (`.github/scripts/issue-triage/issue-context.py`) only read
the template area section or a 6-entry keyword map, and the agent prompt
instructed the model to copy that candidate verbatim (and send `None`
otherwise). The `[Module]` title convention was never consulted.

## Change (two layers)

**1. Deterministic title-prefix matching (primary).** Parse the leading
`[Module]` bracket(s) in the title and match against existing
`Product-*` labels; upgrade the detected area when the body has no area
signal. Fully deterministic and auditable — this alone fixes Screen
Ruler and every other bracketed title.

**2. Constrained AI fallback (secondary).** Expose the repo's
`Product-*` labels as `Available product labels` in the deterministic
evidence, and allow the agent — **only when the deterministic candidate
is `None`** — to select the single best-matching existing label. This is
safe because the publisher already validates the agent's `product_label`
against the real label set, so the agent can only ever **add a valid
existing label**, never invent one or remove/change others.

The workflow prompt is `{{#runtime-import}}`-ed from `issue-triage.md`,
so the lock file changes only by its `body_hash` (sync check);
recompiled with the repo's current gh-aw `v0.84.3` to avoid unrelated
version drift.

## Tests

New unit tests in `tests/test_issue_context.py`:
- `test_title_prefix_maps_to_existing_product_label`
- `test_available_product_labels_are_sorted_and_filtered`
- `test_prepare_labels_bracketed_title_without_area_section`

All 30 tests pass (`python -m unittest tests.test_issue_context`).

## Files
- `.github/scripts/issue-triage/issue-context.py` — title-prefix
detection, available-label list, wiring
- `.github/scripts/issue-triage/tests/test_issue_context.py` — new tests
- `.github/workflows/issue-triage.md` — prompt allows constrained
fallback
- `.github/workflows/issue-triage.lock.yml` — recompiled (`body_hash`
only)

Generated with the GitHub Copilot CLI.

Co-authored-by: niels9001 <niels9001@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26025067-259e-43e3-9dc7-a9fc4b5ba58b
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7b3fb20d-6e9d-4fef-a5cd-f8921d28c220
2026-08-17 12:53:59 +08:00
..