Conversation
- Add .github/workflows/enforce-issue-quality.yml: auto-closes feature requests that lack actionable detail (empty/too-short sections, repeated text, title-only body). Reopens automatically when the author edits the issue to pass validation. Skips trusted contributors (OWNER/MEMBER/COLLABORATOR). - Set blank_issues_enabled: false in .github/ISSUE_TEMPLATE/config.yml to prevent bypassing the structured issue forms. Addresses the class of issues like #208 where the body merely repeats the title with no actionable detail.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63e58456c1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- Pin actions/github-script to immutable SHA matching enforce-pr-target.yml
- Gate on feature-form title prefix AND section headings, not just the
enhancement label, so a mislabeled bug/support issue is never validated
as a feature request
- Use Unicode-aware tokenization (\\p{L}\\p{N}) with a character-count
fallback for unspaced CJK scripts, so localized answers are not closed
as too short
- Restrict getSection lookahead to known template headings so a user H3
inside an answer does not truncate the section
- Fetch live issue state before reopening to avoid a race where a stale
event payload skips the reopen and leaves bot state inactive
- Make the Version field required in the bug report form so reports always include the affected version - Extend the issue-quality enforcer to also validate bug reports, with a deliberately narrow check: only close when both Summary and Reproduction are effectively empty, or when the body merely repeats the title. No word-count floors or section-distinctness rules, so a terse but real crash report is never auto-closed - Detect the form by title prefix AND section headings (not labels) so a mislabeled issue is never validated with the wrong form's rules - Type-aware closing guidance (feature vs bug) - getSection now recognizes bug-form headings as section boundaries
|
Thank you @Wibias for tackling the issue-quality problem — the intent is exactly right. Two design issues prevent us from merging as-is: (1) the reopen logic relies solely on the bot's persistent HTML marker, so it can reopen an issue a maintainer intentionally closed; (2) the workflow also targets bugs despite the title/description claiming feature-only scope. We'd welcome a revised version that tracks manual-closure ownership (check |
Detailed Review — PR #225What we reviewedWe ran an adversarial code review (Sol subagent, gpt-5.6-sol) that read the full FindingsThe intent is exactly right. Low-quality feature requests (empty sections, repeated text, title-only body) are a real problem, and automating their triage is valuable. The exemption for trusted contributors (OWNER/MEMBER/COLLABORATOR) and the use of Three design issues we identified:
Recommendations for a v2
We'd be happy to review a revised version. Thank you @Wibias for the initiative — the automation concept is solid and we want to ship something like this. |
…s on wrong-branch retarget (#229) * feat(issues): redesign OpenCodex issue forms - Bug report: add client/integration and area dropdowns, require version and OS, split logs from screenshots, add upload field for attachments, add redacted-config JSON field. Remove [Bug]: title prefix. - Feature proposal: restructure around goal/blocker/behaviour/example, require a concrete usage example, add workflow-specific checks. Remove [Feature]: title prefix. - New provider/API compatibility form for endpoint, request/response shape, and upstream-spec-anchored reports. - New documentation form for missing, incorrect, outdated, or broken docs. - Disable blank issues (config.yml). * refactor(ci): extract and harden issue-quality validation Move all classification and validation logic into a pure CommonJS module (.github/scripts/issue-quality.cjs) with zero runtime dependencies. The workflow (.github/workflows/enforce-issue-quality.yml) now only handles GitHub API operations: fetching live issue state, managing the hidden bot comment, closing/reopening, and respecting maintainer overrides. Key design decisions: - Detection uses distinct section headings, not title prefixes. - Legacy [Bug]: and [Feature]: prefixed issues remain supported. - Stored bot kind survives heading removal by the author. - No word-count or character-count thresholds anywhere. - Closure ownership: reopen only when the bot's stored closedAt and stateReason exactly match the live issue and no maintainer superseded. - Trusted authors (OWNER/MEMBER/COLLABORATOR) are exempt. - Single hidden bot comment, updated in place (no duplicates). * test(ci): cover issue classification and reopening rules 29 tests using node:test and node:assert/strict (zero dependencies): - Detection: new and legacy forms for all four kinds, stored bot kind, manually applied labels on unrelated issues. - Validation: #208-style duplicates, concise actionable content, CJK submissions, empty reports, terse crash reports, provider-compat missing request/response, documentation corrections. - Normalisation: No response, HTML comments, punctuation, filler phrases. - Closure ownership: timestamp match/mismatch, state reason, inactive bot state, already-open issue, maintainer override. The test workflow runs on PRs and pushes touching the issue templates, validator, or enforcement workflow. It also validates that all issue-form YAML files parse correctly, use only supported element types, and have unique IDs. * chore(ci): minimise PR-target workflow permissions Drop contents: write from enforce-pr-target.yml. The workflow only needs pull-requests: write to update titles, draft status, and comments. No behavioural change. * fix(ci): check closed_by before reopening (owner feedback on #225) The reopen decision now verifies that the bot itself was the last actor to close the issue (closed_by === 'github-actions[bot]'). A human closing the issue, even with a matching timestamp, is treated as intentional closure and the bot will not reopen. Addresses finding 1 from the repo owner's review of PR #225. * fix(ci): prevent false positives on legacy forms and misleading bot comment - Feature validation: blocker and example sections are only required when their headings exist (new form). Legacy forms with only 'Problem to solve' and 'Proposed solution' no longer trigger the missing-sections reason. - Bug validation: version/OS absence only closes when the headings exist in the body. Legacy bug reports without those fields are not penalised. - Workflow: maintainer reopen comment now says 'Maintainer decision respected' instead of 'Automated check passed', which was false when the issue was still invalid. - Tests: two new cases lock in legacy-form compatibility. * feat(issues): use provider-compatibility label on compat form Separates provider/API issues from generic enhancement requests in the issue list. The label needs to be created in the repo by a maintainer: gh label create provider-compatibility --color 0075ca --description 'Incompatible provider, endpoint, or API integration' * fix(ci): address Codex review comments on PR #229 1. Legacy _No response_ in old optional env fields no longer triggers the 'Version and Operating system are both missing' reason. Added isRawPlaceholder() to distinguish intentionally blank optional fields from actively cleared ones. 2. Heading-removal bypass closed: when detectIssueKind() returns null on an edited issue but a form label (bug/enhancement/documentation/provider-compatibility) is still present, the workflow uses that label as a fallback kind instead of skipping enforcement silently. 3. Provider/API compatibility validator now checks that provider and endpoint fields are non-empty. A report where those headings exist but were cleared after submission is rejected. 36 tests pass. * ci: ping PR author when retargeting to dev
…s on wrong-branch retarget (lidge-jun#229) * feat(issues): redesign OpenCodex issue forms - Bug report: add client/integration and area dropdowns, require version and OS, split logs from screenshots, add upload field for attachments, add redacted-config JSON field. Remove [Bug]: title prefix. - Feature proposal: restructure around goal/blocker/behaviour/example, require a concrete usage example, add workflow-specific checks. Remove [Feature]: title prefix. - New provider/API compatibility form for endpoint, request/response shape, and upstream-spec-anchored reports. - New documentation form for missing, incorrect, outdated, or broken docs. - Disable blank issues (config.yml). * refactor(ci): extract and harden issue-quality validation Move all classification and validation logic into a pure CommonJS module (.github/scripts/issue-quality.cjs) with zero runtime dependencies. The workflow (.github/workflows/enforce-issue-quality.yml) now only handles GitHub API operations: fetching live issue state, managing the hidden bot comment, closing/reopening, and respecting maintainer overrides. Key design decisions: - Detection uses distinct section headings, not title prefixes. - Legacy [Bug]: and [Feature]: prefixed issues remain supported. - Stored bot kind survives heading removal by the author. - No word-count or character-count thresholds anywhere. - Closure ownership: reopen only when the bot's stored closedAt and stateReason exactly match the live issue and no maintainer superseded. - Trusted authors (OWNER/MEMBER/COLLABORATOR) are exempt. - Single hidden bot comment, updated in place (no duplicates). * test(ci): cover issue classification and reopening rules 29 tests using node:test and node:assert/strict (zero dependencies): - Detection: new and legacy forms for all four kinds, stored bot kind, manually applied labels on unrelated issues. - Validation: lidge-jun#208-style duplicates, concise actionable content, CJK submissions, empty reports, terse crash reports, provider-compat missing request/response, documentation corrections. - Normalisation: No response, HTML comments, punctuation, filler phrases. - Closure ownership: timestamp match/mismatch, state reason, inactive bot state, already-open issue, maintainer override. The test workflow runs on PRs and pushes touching the issue templates, validator, or enforcement workflow. It also validates that all issue-form YAML files parse correctly, use only supported element types, and have unique IDs. * chore(ci): minimise PR-target workflow permissions Drop contents: write from enforce-pr-target.yml. The workflow only needs pull-requests: write to update titles, draft status, and comments. No behavioural change. * fix(ci): check closed_by before reopening (owner feedback on lidge-jun#225) The reopen decision now verifies that the bot itself was the last actor to close the issue (closed_by === 'github-actions[bot]'). A human closing the issue, even with a matching timestamp, is treated as intentional closure and the bot will not reopen. Addresses finding 1 from the repo owner's review of PR lidge-jun#225. * fix(ci): prevent false positives on legacy forms and misleading bot comment - Feature validation: blocker and example sections are only required when their headings exist (new form). Legacy forms with only 'Problem to solve' and 'Proposed solution' no longer trigger the missing-sections reason. - Bug validation: version/OS absence only closes when the headings exist in the body. Legacy bug reports without those fields are not penalised. - Workflow: maintainer reopen comment now says 'Maintainer decision respected' instead of 'Automated check passed', which was false when the issue was still invalid. - Tests: two new cases lock in legacy-form compatibility. * feat(issues): use provider-compatibility label on compat form Separates provider/API issues from generic enhancement requests in the issue list. The label needs to be created in the repo by a maintainer: gh label create provider-compatibility --color 0075ca --description 'Incompatible provider, endpoint, or API integration' * fix(ci): address Codex review comments on PR lidge-jun#229 1. Legacy _No response_ in old optional env fields no longer triggers the 'Version and Operating system are both missing' reason. Added isRawPlaceholder() to distinguish intentionally blank optional fields from actively cleared ones. 2. Heading-removal bypass closed: when detectIssueKind() returns null on an edited issue but a form label (bug/enhancement/documentation/provider-compatibility) is still present, the workflow uses that label as a fallback kind instead of skipping enforcement silently. 3. Provider/API compatibility validator now checks that provider and endpoint fields are non-empty. A report where those headings exist but were cleared after submission is rejected. 36 tests pass. * ci: ping PR author when retargeting to dev
Summary
Two changes to reduce low-quality issue submissions:
New workflow .github/workflows/enforce-issue-quality.yml: auto-closes feature requests that lack actionable detail (empty/too-short sections, repeated text, title-only body). Reopens automatically when the author edits the issue to pass validation. Skips trusted contributors (OWNER/MEMBER/COLLABORATOR).
Config change .github/ISSUE_TEMPLATE/config.yml: sets \�lank_issues_enabled: false\ to prevent bypassing the structured issue forms entirely.
Motivation
Issues like #208 where the body merely repeats the title with no actionable detail. The structured form fields were being bypassed via blank issues, and even when the form was used, GitHub doesn't validate whether answers are useful.
Review notes