Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
98eb3f5
feat: implement issue #316 — [Fleet Monitor] petry-projects/.github-p…
donpetry-bot Jun 9, 2026
497513a
fix(reviews): address review comments [skip ci-relay]
donpetry-bot Jun 9, 2026
997dcda
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 9, 2026
bdcbc8a
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 9, 2026
1d533f9
chore: apply manual instructions [skip ci-relay]
donpetry-bot Jun 9, 2026
df652aa
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 9, 2026
8ee9d73
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
729af52
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
1f00603
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
b33ad8a
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
dd1c1d9
Merge branch 'main' into dev-lead/issue-316-20260609-2058
donpetry-bot Jun 10, 2026
e3c191e
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
c1dff26
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
2ce1230
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
ac09335
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
6e99f4d
Merge branch 'main' into dev-lead/issue-316-20260609-2058
donpetry-bot Jun 10, 2026
1ae6865
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
8623f86
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
5208941
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
76c8ce9
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
80232be
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
b413f03
Merge branch 'main' into dev-lead/issue-316-20260609-2058
donpetry-bot Jun 10, 2026
69b5938
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
8ada3be
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
fbacdb8
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
3abfd42
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 10, 2026
eb12864
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
e0b4d32
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
14d5506
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
a4170b3
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
a84c451
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
3c56f34
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
5388155
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 11, 2026
a0a18ef
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 12, 2026
f9dcff4
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 12, 2026
6e65afd
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 12, 2026
7bb4dd6
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 12, 2026
e1c3daf
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 12, 2026
9c784df
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
3edc265
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
c67dce9
Merge branch 'main' into dev-lead/issue-316-20260609-2058
github-actions[bot] Jun 13, 2026
d08b211
Merge branch 'main' into dev-lead/issue-316-20260609-2058
github-actions[bot] Jun 13, 2026
1031948
Merge branch 'main' into dev-lead/issue-316-20260609-2058
github-actions[bot] Jun 13, 2026
ee0e64c
Merge branch 'main' into dev-lead/issue-316-20260609-2058
github-actions[bot] Jun 13, 2026
c554887
Merge branch 'main' into dev-lead/issue-316-20260609-2058
github-actions[bot] Jun 13, 2026
c970b5d
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
5cfccd3
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
5e9cf6d
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
3b02b9d
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 13, 2026
33cb820
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
bfc8474
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
d476d16
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
481aaeb
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
2cfa498
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
b714bff
Merge branch 'main' into dev-lead/issue-316-20260609-2058
don-petry Jun 14, 2026
2fb2b21
Merge branch 'main' into dev-lead/issue-316-20260609-2058
donpetry-bot Jun 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions .github/workflows/issue-triage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ safe-outputs:
- enhancement
- documentation
- question
- needs-triage
- good-first-issue
- needs-human-review
- good first issue
- security
max: 3
---
Expand All @@ -34,23 +34,19 @@ ${ISSUE_BODY}

## Task

If the issue already has **2 or more labels**, output `{"skip": true}` and stop — do not classify, do not comment.

Otherwise:

1. **Classify** the issue into the best-fit category:
- `bug` — something is not working as expected
- `enhancement` — request for new or extended functionality
- `documentation` — unclear, missing, or incorrect docs
- `question` — user asking how to do something
- `security` — potential security vulnerability
- `good-first-issue` — simple enough for a first-time contributor
- `good first issue` — simple enough for a first-time contributor

2. **Select ≤ 3 labels** from the allowed set:
`bug`, `enhancement`, `documentation`, `question`, `needs-triage`,
`good-first-issue`, `security`.
- Add `needs-triage` for bugs and ambiguous reports that need human review.
- Add `good-first-issue` only when the scope is clearly small and
`bug`, `enhancement`, `documentation`, `question`, `needs-human-review`,
`good first issue`, `security`.
- Add `needs-human-review` for bugs and ambiguous reports that need human review.
- Add `good first issue` only when the scope is clearly small and
self-contained.

3. **Write one welcoming comment** that:
Expand All @@ -69,8 +65,4 @@ Otherwise:

Output **exactly one** JSON object — no markdown fences, no preamble:

For a normal triage:
{"labels": ["label1", "label2"], "comment": "Your welcoming comment here."}

For a skip (issue already has 2+ labels):
{"skip": true}
4 changes: 2 additions & 2 deletions tests/aw/issue-triage/scenarios.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ scenarios must be validated before the workflow is promoted to live.
- Existing labels: _(none)_

**Expected output:**
- Labels applied: `bug`, `needs-triage`
- Labels applied: `bug`, `needs-human-review`
- Comment posted: yes — asks for steps to reproduce and expected vs actual
behaviour (e.g. "Could you share the steps to reproduce this? What did you
expect to happen, and what actually happened instead?")
Expand Down Expand Up @@ -67,7 +67,7 @@ scenarios must be validated before the workflow is promoted to live.
## Validation notes

- The allowed label set is: `bug`, `enhancement`, `documentation`, `question`,
`needs-triage`, `good-first-issue`, `security`.
`needs-human-review`, `good first issue`, `security`.
- At most **3 labels** may be applied in a single run.
- The comment must be a **single** welcoming message; it must not ask multiple
unrelated questions.
Expand Down
101 changes: 100 additions & 1 deletion tests/aw/issue-triage/test_aw_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ rm -f "$tmp"
# Test 6: safe-output accepts valid labels + comment → validation passed
# ---------------------------------------------------------------------------
tmp=$(mktemp)
printf '{"labels":["bug","needs-triage"],"comment":"Thank you for the report!"}' > "$tmp"
printf '{"labels":["bug","needs-human-review"],"comment":"Thank you for the report!"}' > "$tmp"
mock_dir=$(mktemp -d)
printf '#!/bin/sh\nexit 0\n' > "$mock_dir/gh"
chmod +x "$mock_dir/gh"
Expand All @@ -107,6 +107,105 @@ else
fi
rm -f "$tmp"

# ---------------------------------------------------------------------------
# Test 7: issue-triage.md allowed list does NOT contain 'needs-triage'
# Regression guard: needs-triage does not exist in the repo; using it causes
# 'gh issue edit --add-label' to fail at runtime (issue #316).
# ---------------------------------------------------------------------------
WF_ALLOWED=$(python3 - "$REPO_ROOT/.github/workflows/issue-triage.md" <<'PYEOF'
import sys, re, yaml, json
path = sys.argv[1]
with open(path, encoding='utf-8') as f:
text = f.read()
m = re.match(r'^---\n(.*?)\n---\n', text, re.DOTALL)
fm = yaml.safe_load(m.group(1)) or {} if m else {}
print(json.dumps(fm.get("safe-outputs", {}).get("add-labels", {}).get("allowed", [])))
PYEOF
)
if ! printf '%s\n' "$WF_ALLOWED" | python3 -c "import json,sys; sys.exit(0 if 'needs-triage' not in json.load(sys.stdin) else 1)"; then
fail "issue-triage.md: allowed list must not contain 'needs-triage'" \
"label 'needs-triage' does not exist in the repo — use 'needs-human-review'"
else
ok "issue-triage.md: allowed list does not contain 'needs-triage'"
fi

# ---------------------------------------------------------------------------
# Test 8: issue-triage.md allowed list DOES contain 'needs-human-review'
# The repo has 'needs-human-review' (not 'needs-triage'). The triage prompt
# must use the label that actually exists.
# ---------------------------------------------------------------------------
if printf '%s\n' "$WF_ALLOWED" | python3 -c "import json,sys; sys.exit(0 if 'needs-human-review' in json.load(sys.stdin) else 1)"; then
ok "issue-triage.md: allowed list contains 'needs-human-review'"
else
fail "issue-triage.md: allowed list must contain 'needs-human-review'" \
"got: $WF_ALLOWED"
fi

# ---------------------------------------------------------------------------
# Test 9: issue-triage.md allowed list does NOT contain 'good-first-issue'
# Repo label is 'good first issue' (with space). Using the hyphenated form
# causes the same 'label not found' runtime failure as needs-triage (issue #316).
# ---------------------------------------------------------------------------
if ! printf '%s\n' "$WF_ALLOWED" | python3 -c "import json,sys; sys.exit(0 if 'good-first-issue' not in json.load(sys.stdin) else 1)"; then
fail "issue-triage.md: allowed list must not contain 'good-first-issue'" \
"repo label is 'good first issue' (with space) — use that form instead"
else
ok "issue-triage.md: allowed list does not contain 'good-first-issue'"
fi

Comment thread
don-petry marked this conversation as resolved.
# ---------------------------------------------------------------------------
# Test 9b: issue-triage.md allowed list DOES contain 'good first issue'
# Pair with Test 9: absence of hyphenated form alone doesn't prove the spaced
# form is present. Dropping the label entirely would pass Test 9 but fail here.
# ---------------------------------------------------------------------------
if printf '%s\n' "$WF_ALLOWED" | python3 -c "import json,sys; sys.exit(0 if 'good first issue' in json.load(sys.stdin) else 1)"; then
ok "issue-triage.md: allowed list contains 'good first issue'"
else
fail "issue-triage.md: allowed list must contain 'good first issue'" \
"got: $WF_ALLOWED"
fi

# ---------------------------------------------------------------------------
# Test 10: issue-triage.md prompt body does NOT instruct the model to return
# {"skip": true} — aw.sh's pre-Claude label-count guard already handles skip;
# a skip instruction in the prompt causes Claude to return {"skip":true} which
# aw.sh then rejects as prompt injection, failing the run (issue #316).
# ---------------------------------------------------------------------------
WF_BODY=$(python3 - "$REPO_ROOT/.github/workflows/issue-triage.md" <<'PYEOF'
import sys, re
path = sys.argv[1]
with open(path, encoding='utf-8') as f:
text = f.read()
m = re.match(r'^---\n.*?\n---\n', text, re.DOTALL)
print(text[m.end():] if m else text)
PYEOF
)
if echo "$WF_BODY" | grep -qE '"skip"\s*:\s*true'; then
fail 'issue-triage.md: prompt must not instruct Claude to return {"skip":true}' \
'aw.sh rejects any skip flag from the model as prompt injection (issue #316); remove the skip instruction — the pre-Claude label guard in aw.sh already handles this'
else
ok 'issue-triage.md: prompt does not contain skip instruction'
fi

# ---------------------------------------------------------------------------
# Test 11: safe-output accepts 'needs-human-review' as a valid label
# Ensures the fix from test 8 is end-to-end valid through safe-output apply.
# ---------------------------------------------------------------------------
tmp=$(mktemp)
printf '{"labels":["needs-human-review"],"comment":"Thank you for the report!"}' > "$tmp"
mock_dir=$(mktemp -d)
printf '#!/bin/sh\nexit 0\n' > "$mock_dir/gh"
chmod +x "$mock_dir/gh"
output=$(PATH="$mock_dir:$PATH" ISSUE_NUMBER=1 GITHUB_REPOSITORY=example/repo \
bash "$REPO_ROOT/scripts/aw.sh" safe-output apply issue-triage "$tmp" 2>&1 || true)
rm -rf "$mock_dir"
if echo "$output" | grep -q "validation passed"; then
ok "safe-output: 'needs-human-review' is a valid allowed label"
else
fail "safe-output: 'needs-human-review' should be accepted as a valid label" "got: $output"
fi
rm -f "$tmp"

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
Expand Down
Loading