Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 12 additions & 5 deletions .github/scripts/issue-quality-core.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,10 +1134,8 @@ const REPRO_PATH_RE = new RegExp([
"~?/[\\w.@-]+(?:/[\\w.@-]+)+",
"[A-Za-z]:\\\\(?:[\\w.@-]+\\\\)+[\\w.@-]+",
"~?/[\\w.@-]+/[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env|txt|ts|js|tsx|jsx|sh|ps1|py)",
"[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b",
].join("|"));
const ACTIONABLE_REPRO_RE = new RegExp(
[REPRO_COMMAND_RE.source, REPRO_FAILURE_RE.source, REPRO_PATH_RE.source].join("|"),
"(?:^|[^\\w.@-])[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b",
].join("|"),
Comment on lines +1137 to +1138

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add a trailing filename boundary.

Line 1137 uses \b, which only checks a word/non-word transition. It succeeds before ., -, and @. Therefore, CONFIG.JSON.bak and CONFIG.JSON-backup can match the CONFIG.JSON prefix and return true, even though the final filename extension is unsupported.

Add a filename-aware trailing boundary and regression tests. Preserve terminal punctuation if that punctuation is valid input.

Proposed fix
-    "(?:^|[^\\w.@-])[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b",
+    "(?:^|[^\\w.@-])[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b(?![.@-][\\w.@-])",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"(?:^|[^\\w.@-])[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b",
].join("|"),
"(?:^|[^\\w.@-])[\\w.@-]+\\.(?:json|yaml|yml|toml|conf|log|env)\\b(?![.@-][\\w.@-])",
].join("|"),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/issue-quality-core.cjs around lines 1137 - 1138, Update the
filename-pattern entry in the issue-quality validation rules to require a
filename-aware trailing boundary after supported extensions, preventing prefixes
such as CONFIG.JSON.bak and CONFIG.JSON-backup from matching while preserving
valid terminal punctuation. Add regression tests covering unsupported suffixes
and accepted punctuation, using the existing validation test structure.

"i",
);

Expand All @@ -1151,9 +1149,18 @@ const EMPTY_FENCE_RE = /^[ \t]{0,3}(?:```+|~~~+)\s*\n\s*\n[ \t]{0,3}(?:```+|~~~+
* count as actionable when their body contains non-whitespace content.
*/
function hasActionableReproductionDetail(text) {
if (typeof text !== "string") return false;
// Avoid Markdown cleanup and path matching when the raw input cannot contain
// actionable syntax. Fences remain eligible through their ` / ~ sigils.
if (!/[./\\`~]/.test(text) && !REPRO_COMMAND_RE.test(text) && !REPRO_FAILURE_RE.test(text)) {
return false;
}
const c = clean(text);
if (!c) return false;
if (ACTIONABLE_REPRO_RE.test(c)) return true;
if (REPRO_COMMAND_RE.test(c) || REPRO_FAILURE_RE.test(c)) return true;
// A boundary-anchored filename avoids retrying the same long token from each
// successive character while preserving case-insensitive extension matches.
if (/[./\\]/.test(c) && REPRO_PATH_RE.test(c)) return true;
// Fenced blocks: only count when the body has non-whitespace content.
if (/```|~~~/.test(c)) {
const parts = stripFencedActionableContent(c);
Expand Down
7 changes: 7 additions & 0 deletions .github/scripts/issue-quality.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,13 @@ describe("validateIssue - feature", () => {
assert.equal(hasActionableReproductionDetail("```\nSIGSEGV at 0x0000\n```"), true);
});

it("bounds long non-matching reproduction path tokens", () => {
const startedAt = performance.now();
assert.equal(hasActionableReproductionDetail(`${"a".repeat(60_000)}.unknown`), false);
assert.ok(performance.now() - startedAt < 500, "actionable reproduction check took too long");
assert.equal(hasActionableReproductionDetail("CONFIG.JSON"), true);
});

it("rejects fenced placeholder-only examples", () => {
const fencedPlaceholders = [
"```\nN/A\n```",
Expand Down
Loading