Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
12 changes: 8 additions & 4 deletions .github/scripts/issue_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
sit inside a ```bash fence validates as conforming — a false negative that lets
an unactionable issue through the guard. Well-written issues quote commands and
expected output in fences constantly, so this is the common case, not an edge
one. Any change to heading detection must keep a fenced-heading case in
tests/scripts/test_issue_format.py.
one. Any change to heading detection must keep a fenced-heading case in the
upstream Workflows test `tests/scripts/test_issue_format.py`.

Pure stdlib on purpose — it must run on a bare runner with no install step.
"""
Expand Down Expand Up @@ -83,7 +83,11 @@
marker = fence_match.group(1)
if fence is None:
fence = (marker[0], len(marker))
elif marker[0] == fence[0] and len(marker) >= fence[1]:
elif (
marker[0] == fence[0]
and len(marker) >= fence[1]
and re.fullmatch(r"\s{0,3}(?:`{%d,}|~{%d,})\s*" % (fence[1], fence[1]), line)

Check failure on line 89 in .github/scripts/issue_format.py

View workflow job for this annotation

GitHub Actions / python ci / lint-ruff

ruff (UP031)

.github/scripts/issue_format.py:89:34: UP031 Use format specifiers instead of percent format help: Replace with format specifiers
):
fence = None
continue
if fence is not None:
Expand All @@ -96,7 +100,7 @@

def _find(body: str, aliases: tuple[str, ...]) -> int | None:
for text, idx, _ in _headings(body):
if text in aliases:
if any(text == alias or text.startswith(f"{alias} (") for alias in aliases):
return idx
return None

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/agents-issue-format-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ jobs:
exit "$rc"
fi

- name: Invalidate stale format completion after an invalid edit
- name: Invalidate stale format completion after an invalid issue change
if: >-
steps.issue.outputs.exempt != 'true' && github.event.action == 'edited' &&
steps.validate.outputs.rc == '1'
steps.issue.outputs.exempt != 'true' && steps.validate.outputs.rc == '1'
Comment thread
stranske marked this conversation as resolved.
Resolved
env:
GH_TOKEN: ${{ github.token }}
NUMBER: ${{ steps.issue.outputs.number }}
run: |
set -euo pipefail
if gh issue view "$NUMBER" --repo "$GITHUB_REPOSITORY" --json labels \
--jq '.labels[].name' | grep -qx 'agents:formatted'; then
gh issue edit "$NUMBER" --repo "$GITHUB_REPOSITORY" --remove-label "agents:formatted"
echo "Invalid issue edit — cleared agents:formatted before rerouting."
gh issue edit "$NUMBER" --repo "$GITHUB_REPOSITORY" --remove-label "agents:formatted" \
|| echo "::warning::could not remove stale agents:formatted"
echo "Invalid issue body — cleared agents:formatted before rerouting."
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
Comment thread
stranske marked this conversation as resolved.
Resolved
fi

- name: Route non-conforming issue to the optimizer
Expand Down
12 changes: 8 additions & 4 deletions templates/consumer-repo/.github/scripts/issue_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
sit inside a ```bash fence validates as conforming — a false negative that lets
an unactionable issue through the guard. Well-written issues quote commands and
expected output in fences constantly, so this is the common case, not an edge
one. Any change to heading detection must keep a fenced-heading case in
tests/scripts/test_issue_format.py.
one. Any change to heading detection must keep a fenced-heading case in the
upstream Workflows test `tests/scripts/test_issue_format.py`.

Pure stdlib on purpose — it must run on a bare runner with no install step.
"""
Expand Down Expand Up @@ -83,7 +83,11 @@
marker = fence_match.group(1)
if fence is None:
fence = (marker[0], len(marker))
elif marker[0] == fence[0] and len(marker) >= fence[1]:
elif (
marker[0] == fence[0]
and len(marker) >= fence[1]
and re.fullmatch(r"\s{0,3}(?:`{%d,}|~{%d,})\s*" % (fence[1], fence[1]), line)

Check failure on line 89 in templates/consumer-repo/.github/scripts/issue_format.py

View workflow job for this annotation

GitHub Actions / python ci / lint-ruff

ruff (UP031)

templates/consumer-repo/.github/scripts/issue_format.py:89:34: UP031 Use format specifiers instead of percent format help: Replace with format specifiers
):
fence = None
continue
if fence is not None:
Expand All @@ -96,7 +100,7 @@

def _find(body: str, aliases: tuple[str, ...]) -> int | None:
for text, idx, _ in _headings(body):
if text in aliases:
if any(text == alias or text.startswith(f"{alias} (") for alias in aliases):
return idx
return None

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ jobs:
exit "$rc"
fi

- name: Invalidate stale format completion after an invalid edit
- name: Invalidate stale format completion after an invalid issue change
if: >-
steps.issue.outputs.exempt != 'true' && github.event.action == 'edited' &&
steps.validate.outputs.rc == '1'
steps.issue.outputs.exempt != 'true' && steps.validate.outputs.rc == '1'
env:
GH_TOKEN: ${{ github.token }}
NUMBER: ${{ steps.issue.outputs.number }}
run: |
set -euo pipefail
if gh issue view "$NUMBER" --repo "$GITHUB_REPOSITORY" --json labels \
--jq '.labels[].name' | grep -qx 'agents:formatted'; then
gh issue edit "$NUMBER" --repo "$GITHUB_REPOSITORY" --remove-label "agents:formatted"
echo "Invalid issue edit — cleared agents:formatted before rerouting."
gh issue edit "$NUMBER" --repo "$GITHUB_REPOSITORY" --remove-label "agents:formatted" \
|| echo "::warning::could not remove stale agents:formatted"
echo "Invalid issue body — cleared agents:formatted before rerouting."
Comment thread
stranske marked this conversation as resolved.
Resolved
fi

- name: Route non-conforming issue to the optimizer
Expand Down
20 changes: 20 additions & 0 deletions tests/scripts/test_issue_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ def test_fenced_headings_do_not_satisfy_required_sections() -> None:
assert set(report.missing_required) == {"Tasks", "Acceptance Criteria"}


def test_fence_with_language_marker_does_not_close_a_code_block() -> None:
validator = _validator()
report = validator.validate(
"```markdown\n## Tasks\n- [ ] pretend\n```python\n"
"## Acceptance Criteria\n- pytest tests/test_x.py\n````\n"
)
assert not report.ok
assert "Acceptance Criteria" in report.missing_required


def test_heading_with_trailing_qualifier_matches_required_section() -> None:
validator = _validator()
report = validator.validate(
VALID_CONTEXT
+ "## Tasks (in order)\n- [ ] Implement it\n\n"
+ "## Acceptance Criteria (all must hold)\n- pytest tests/test_x.py passes\n"
)
assert report.ok


def test_checkbox_and_subjective_errors_are_non_conforming() -> None:
validator = _validator()
report = validator.validate(
Expand Down
Loading