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
10 changes: 5 additions & 5 deletions .github/scripts/__tests__/keepalive-loop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2831,8 +2831,8 @@ test('analyzeTaskCompletion uses lowered 35% threshold with file match', async (
assert.equal(configMatch.confidence, 'high', 'Should be high confidence with 35%+ match and file touch');
});

test('analyzeTaskCompletion gives high confidence for 25% keyword match with file match', async () => {
// Lower threshold: 25% keyword match + file match = high confidence
test('analyzeTaskCompletion gives medium confidence for 25% keyword match with file match', async () => {
// Stricter thresholds: 25% keyword match + file match = medium confidence (was high before tightening)
const commits = [
{ sha: 'abc123', commit: { message: 'add wizard step' } },
];
Expand Down Expand Up @@ -2874,7 +2874,7 @@ test('analyzeTaskCompletion gives high confidence for 25% keyword match with fil
m.task.toLowerCase().includes('wizard')
);
assert.ok(wizardMatch, 'Should match wizard task');
assert.equal(wizardMatch.confidence, 'high', 'Should be high confidence with file match even at ~25% keywords');
assert.equal(wizardMatch.confidence, 'medium', 'Should be medium confidence with file match at ~25% keywords (stricter thresholds)');
});

test('analyzeTaskCompletion uses synonym expansion for better matching', async () => {
Expand Down Expand Up @@ -2921,7 +2921,7 @@ test('analyzeTaskCompletion uses synonym expansion for better matching', async (
m.task.toLowerCase().includes('config validation')
);
assert.ok(configMatch, 'Should match config validation task');
assert.equal(configMatch.confidence, 'high', 'Should be high confidence with synonym matching');
assert.equal(configMatch.confidence, 'medium', 'Should be medium confidence with synonym matching (stricter thresholds)');
});

test('analyzeTaskCompletion skips when repo context is missing', async () => {
Expand Down Expand Up @@ -3122,7 +3122,7 @@ test('autoReconcileTasks updates PR body for high-confidence matches', async ()

assert.ok(result.updated, 'Should update PR body');
assert.ok(result.tasksChecked > 0, 'Should check at least one task');
assert.equal(result.sources.commit, 2, 'Should report commit-based source count');
assert.equal(result.sources.commit, 1, 'Should report commit-based source count (stricter matching reduces to 1)');
assert.equal(result.sources.llm, 0, 'Should report no LLM sources');

if (updatedBody) {
Expand Down
5 changes: 3 additions & 2 deletions .github/scripts/keepalive_loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,6 @@ function countCheckboxes(markdown) {
// must be independently verified, not auto-checked by parent cascade.
const ACCEPTANCE_HEADING_PATTERNS = [
/acceptance\s*criteria/i,
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The PR description states that the removed pattern was /^acceptance$/i (with anchors), but the actual removed pattern shown in the diff and code history is /acceptance/i (without anchors). The pattern without anchors is actually MORE overly broad than the description suggests, since it matches "acceptance" anywhere in the heading text, not just as an exact match. While the fix is correct, the PR description should be updated to accurately reflect which pattern was removed.

Copilot uses AI. Check for mistakes.
/acceptance/i,
/definition\s*of\s*done/i,
/done\s*criteria/i,
Comment on lines 861 to 864
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match plain Acceptance headings in cascade guard

Dropping the broad acceptance pattern also removes detection of the supported Acceptance heading alias, so isAcceptanceHeading no longer suppresses cascade in sections titled ## Acceptance. Since section parsing still accepts Acceptance (issue_scope_parser.js aliases), this mismatch allows parent-to-child auto-checking inside acceptance criteria for that heading style, which can incorrectly reduce unchecked counts and let completion logic advance too early.

Useful? React with 👍 / 👎.

];
Expand Down Expand Up @@ -3583,10 +3582,12 @@ async function updateKeepaliveLoopSummary({ github: rawGithub, context, core, in
: {};
if (tasksUnchecked > 0) {
verification = {};
} else if (reason === 'verify-acceptance') {
} else if (reason === 'verify-acceptance' || reason === 'fix-verification-gaps') {
const previousAttemptCount = toNumber(verification?.attempt_count, 0);
verification = {
status: runResult === 'success' ? 'done' : 'failed',
Comment on lines +3585 to 3588
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not mark fix-verification runs as verified

This change now treats reason === 'fix-verification-gaps' as a verification attempt and sets verification.status to done on any successful run, but that run is not guaranteed to be an acceptance verification pass (the routing logic still maps fix-* reasons to fix_ci mode in keepalive_prompt_routing.js). Because evaluateKeepaliveLoop stops when verificationDone is true, a successful fixer run can prematurely end the loop without a fresh verifier pass, leaving acceptance gaps unverified.

Useful? React with 👍 / 👎.

iteration: nextIteration,
attempt_count: previousAttemptCount + 1,
last_result: runResult || '',
updated_at: new Date().toISOString(),
};
Expand Down
5 changes: 3 additions & 2 deletions templates/consumer-repo/.github/scripts/keepalive_loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,6 @@ function countCheckboxes(markdown) {
// must be independently verified, not auto-checked by parent cascade.
const ACCEPTANCE_HEADING_PATTERNS = [
/acceptance\s*criteria/i,
/acceptance/i,
/definition\s*of\s*done/i,
/done\s*criteria/i,
];
Expand Down Expand Up @@ -3583,10 +3582,12 @@ async function updateKeepaliveLoopSummary({ github: rawGithub, context, core, in
: {};
if (tasksUnchecked > 0) {
verification = {};
} else if (reason === 'verify-acceptance') {
} else if (reason === 'verify-acceptance' || reason === 'fix-verification-gaps') {
const previousAttemptCount = toNumber(verification?.attempt_count, 0);
verification = {
status: runResult === 'success' ? 'done' : 'failed',
iteration: nextIteration,
attempt_count: previousAttemptCount + 1,
last_result: runResult || '',
updated_at: new Date().toISOString(),
};
Expand Down
Loading