Skip to content
3 changes: 2 additions & 1 deletion .github/scripts/__tests__/issue_scope_parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,10 @@ test('extracts "To Do" as Tasks alias', () => {

test('hasNonPlaceholderScopeTasksAcceptanceContent detects PR meta fallback placeholders', () => {
// Content with only PR meta manager fallback placeholders should return false
// Note: scope uses italicized text (not checkbox) since it's informational
const prMetaPlaceholders = [
'## Scope',
'- [ ] Scope section missing from source issue.',
'_Scope section missing from source issue._',
'',
'## Tasks',
'- [ ] Tasks section missing from source issue.',
Expand Down
3 changes: 2 additions & 1 deletion .github/scripts/issue_scope_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ const PLACEHOLDERS = {
};

// Fallback placeholders used by PR meta manager when source issue lacks sections
// Note: scope uses plain text (not checkbox) since it's informational, not actionable
const PR_META_FALLBACK_PLACEHOLDERS = {
scope: '- [ ] Scope section missing from source issue.',
scope: '_Scope section missing from source issue._',
tasks: '- [ ] Tasks section missing from source issue.',
Comment thread
stranske marked this conversation as resolved.
acceptance: '- [ ] Acceptance criteria section missing from source issue.',
};
Expand Down
47 changes: 44 additions & 3 deletions .github/scripts/verifier_issue_formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,45 @@ function looksLikeReferenceLink(text) {
return /^[-–•]?\s*(PR|Issue|Pull\s+Request)\s*#\d+/i.test(trimmed);
}

/**
* Convert checkbox items to plain text bullets.
* Scope is informational, not something to be checked off.
* Also filters out empty/blank lines and placeholder content.
*
* @param {string} content - Content possibly containing checkboxes
* @returns {string} Content with checkboxes converted to plain bullets
*/
function stripCheckboxesFromScope(content) {
if (!content) return '';

const lines = String(content).split('\n');
const result = [];

for (const line of lines) {
const trimmed = line.trim();

// Skip empty lines
if (!trimmed) continue;

// Skip placeholder content
if (isPlaceholderContent(trimmed)) continue;

// Convert checkbox to plain bullet
const checkboxMatch = line.match(/^(\s*)[-*]\s+\[[\sxX]\]\s+(.+)$/);
Comment thread
stranske marked this conversation as resolved.
Outdated
if (checkboxMatch) {
const [, indent, text] = checkboxMatch;
// Skip if text is also a placeholder
if (!isPlaceholderContent(text)) {
result.push(`${indent}- ${text}`);
}
} else {
result.push(line);
}
}

return result.join('\n');
}
Comment thread
stranske marked this conversation as resolved.

/**
* Simple similarity score between two strings (0-1).
* Uses Jaccard similarity on word sets for fuzzy matching.
Expand Down Expand Up @@ -466,9 +505,10 @@ function formatFollowUpIssue({
sections.push(['## Why', '', `<!-- Preserved from parent issue -->`, why].join('\n'));
}

// Scope section
if (merged.scope) {
sections.push(['## Scope', '', `<!-- Updated scope for this follow-up -->`, `Address unmet acceptance criteria from PR #${prNumber || 'N/A'}.`, '', 'Original scope:', merged.scope].join('\n'));
// Scope section - strip checkboxes since scope is informational, not actionable
const cleanedScope = stripCheckboxesFromScope(merged.scope);
if (cleanedScope) {
sections.push(['## Scope', '', `<!-- Updated scope for this follow-up -->`, `Address unmet acceptance criteria from PR #${prNumber || 'N/A'}.`, '', 'Original scope:', cleanedScope].join('\n'));
} else {
sections.push(['## Scope', '', `Address unmet acceptance criteria from PR #${prNumber || 'N/A'}.`].join('\n'));
}
Expand Down Expand Up @@ -608,4 +648,5 @@ module.exports = {
isPlaceholderContent,
looksLikeSectionHeader,
looksLikeReferenceLink,
stripCheckboxesFromScope,
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ const PLACEHOLDERS = {
};

// Fallback placeholders used by PR meta manager when source issue lacks sections
// Note: scope uses plain text (not checkbox) since it's informational, not actionable
const PR_META_FALLBACK_PLACEHOLDERS = {
scope: '- [ ] Scope section missing from source issue.',
scope: '_Scope section missing from source issue._',
tasks: '- [ ] Tasks section missing from source issue.',
acceptance: '- [ ] Acceptance criteria section missing from source issue.',
};
Expand Down
Loading