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
101 changes: 101 additions & 0 deletions .github/scripts/__tests__/keepalive-loop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,62 @@ test('updateKeepaliveLoopSummary increments iteration and clears failures on suc
assert.match(github.actions[0].body, /"failure":\{\}/);
});

test('updateKeepaliveLoopSummary ignores status-only checklist metrics for reconciliation', async () => {
const pr = {
number: 1234,
labels: [{ name: 'agent:codex' }],
body: [
'## Tasks',
'- [ ] Updated: 2026-04-26T12:33:27.204Z',
'- [ ] Repos checked: 11/11',
'- [ ] Open sync PRs: 439',
'',
'## Acceptance Criteria',
'- [ ] Acceptance criteria section missing from source issue.',
].join('\n'),
};
const existingState = formatStateComment({
trace: 'status-only-trace',
iteration: 2,
max_iterations: 5,
tasks: { total: 13, unchecked: 13 },
});
const github = buildGithubStub({
pr,
comments: [{ id: 91, body: existingState, html_url: 'https://example.com/91' }],
});

await updateKeepaliveLoopSummary({
github,
context: buildContext(pr.number),
core: buildCore(),
inputs: {
prNumber: pr.number,
action: 'run',
runResult: 'success',
gateConclusion: 'success',
tasksTotal: 13,
tasksUnchecked: 13,
keepaliveEnabled: true,
autofixEnabled: false,
iteration: 2,
maxIterations: 5,
failureThreshold: 3,
trace: 'status-only-trace',
codex_changes_made: 'true',
codex_files_changed: 2,
codex_commit_sha: 'deadbeef',
codex_summary: 'Changed keepalive parser behavior for status metrics.',
},
});

assert.equal(github.actions.length, 2);
const parsedState = parseStateComment(github.actions[0].body);
assert.ok(parsedState);
assert.deepEqual(parsedState.data.tasks, { total: 0, unchecked: 0 });
assert.equal(parsedState.data.needs_task_reconciliation, false);
});

test('updateKeepaliveLoopSummary reuses cached PR data for labels and body', async () => {
const pr = {
number: 321,
Expand Down Expand Up @@ -2419,6 +2475,51 @@ test('buildTaskAppendix highlights attempted tasks and suggests next task', () =
assert.ok(appendix.includes('- Task B'));
});

test('buildTaskAppendix does not suggest status-metric checklist items as next task', () => {
const { buildTaskAppendix } = require('../keepalive_loop.js');
const sections = {
tasks: [
'- [ ] Updated: 2026-04-26T12:33:27.204Z',
'- [ ] Repos checked: 11/11',
'- [ ] Open sync PRs: 439',
].join('\n'),
acceptance: '- [ ] Acceptance criteria section missing from source issue.',
};
const checkboxCounts = { total: 0, checked: 0, unchecked: 0 };

const appendix = buildTaskAppendix(sections, checkboxCounts, {});
assert.ok(!appendix.includes('### Suggested Next Task'));
});

test('evaluateKeepaliveLoop stops with no-checklists when only status metrics/placeholders exist', async () => {
const pr = {
number: 113,
head: { ref: 'feature/status-metrics-only', sha: 'sha-13' },
labels: [{ name: 'agent:codex' }],
body: [
'## Tasks',
'- [ ] Updated: 2026-04-26T12:33:27.204Z',
'- [ ] Repos checked: 11/11',
'- [ ] Open sync PRs: 439',
'',
'## Acceptance Criteria',
'- [ ] Acceptance criteria section missing from source issue.',
].join('\n'),
};
const github = buildGithubStub({
pr,
workflowRuns: [{ head_sha: 'sha-13', conclusion: 'success' }],
});
const result = await evaluateKeepaliveLoop({
github,
context: buildContext(pr.number),
core: buildCore(),
});
assert.equal(result.action, 'stop');
assert.equal(result.reason, 'no-checklists');
assert.deepEqual(result.checkboxCounts, { total: 0, checked: 0, unchecked: 0 });
});

test('markAgentRunning updates summary comment with running status', async () => {
// Use formatStateComment to create proper state marker
const existingStateBody = formatStateComment({
Expand Down
85 changes: 56 additions & 29 deletions .github/scripts/__tests__/terminal-disposition-coverage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,9 @@ test('summarizes verifier model compatibility with configurable unsupported mode
]);
assert.equal(
normalizeVerifierModelMetadataContract().required_after,
'2026-04-26T04:25:00Z'
''
);
assert.equal(normalizeVerifierModelMetadataContract().model_metadata_required, false);

const summary = summarizeVerifierModelCompatibility(
[
Expand Down Expand Up @@ -288,27 +289,32 @@ test('summarizes verifier model compatibility with configurable unsupported mode
});

test('warns when Codex verifier terminal records omit model metadata', () => {
const report = summarizeTerminalDispositionCoverage([
{
schema: 'workflows-terminal-disposition/v1',
artifact_family: 'verifier-terminal-disposition',
source_type: 'pull-request',
source_id: '1872',
pr_number: 1872,
run_id: '24948023778',
disposition: 'verifier-error',
verifier_mode: 'compare',
},
const report = summarizeTerminalDispositionCoverage(
[
{
schema: 'workflows-terminal-disposition/v1',
artifact_family: 'verifier-terminal-disposition',
source_type: 'pull-request',
source_id: '1872',
pr_number: 1872,
run_id: '24948023778',
disposition: 'verifier-error',
verifier_mode: 'compare',
},
{
schema: 'workflows-terminal-disposition/v1',
artifact_family: 'verifier-terminal-disposition',
source_type: 'pull-request',
source_id: '1873',
pr_number: 1873,
disposition: 'verified-pass',
verifier_mode: 'evaluate',
},
],
{
schema: 'workflows-terminal-disposition/v1',
artifact_family: 'verifier-terminal-disposition',
source_type: 'pull-request',
source_id: '1873',
pr_number: 1873,
disposition: 'verified-pass',
verifier_mode: 'evaluate',
},
]);
model_metadata_required_after: '2026-04-26T04:25:00Z',
}
);
const markdown = formatTerminalDispositionCoverageMarkdown(report);

assert.equal(report.status, 'warning');
Expand All @@ -317,13 +323,13 @@ test('warns when Codex verifier terminal records omit model metadata', () => {
report.verifier_model_compatibility.missing_model_records.map((record) => record.source_key),
['pull-request:1872']
);
assert.deepEqual(report.enforcement.blockers, ['unsupported-verifier-model']);
assert.deepEqual(report.enforcement.blockers, ['missing-verifier-model-metadata']);
assert.match(markdown, /Missing verifier model metadata records: 1/);
assert.match(markdown, /pull-request:1872/);
assert.doesNotMatch(markdown, /\| pull-request:1873 \| verified-pass \| evaluate/);
});

test('warns when verifier terminal model metadata is missing with unknown mode', () => {
test('does not require verifier model metadata when mode is unknown', () => {
const report = summarizeTerminalDispositionCoverage([
{
schema: 'workflows-terminal-disposition/v1',
Expand All @@ -337,11 +343,10 @@ test('warns when verifier terminal model metadata is missing with unknown mode',
},
]);

assert.equal(report.status, 'warning');
assert.equal(report.verifier_model_compatibility.status, 'warning');
assert.equal(report.verifier_model_compatibility.missing_model_record_count, 1);
assert.equal(report.verifier_model_compatibility.missing_model_records[0].verifier_mode, 'unknown');
assert.deepEqual(report.enforcement.blockers, ['unsupported-verifier-model']);
assert.equal(report.status, 'pass');
assert.equal(report.verifier_model_compatibility.status, 'pass');
assert.equal(report.verifier_model_compatibility.missing_model_record_count, 0);
assert.deepEqual(report.enforcement.blockers, []);
});

test('suppresses pre-contract verifier terminal records missing model metadata', () => {
Expand All @@ -359,6 +364,7 @@ test('suppresses pre-contract verifier terminal records missing model metadata',
},
],
{
model_metadata_required_after: '2026-04-26T04:25:00Z',
input_file_count: 1,
artifact_selection_report: {
schema: 'workflows-weekly-metrics-artifact-selection/v1',
Expand Down Expand Up @@ -400,6 +406,7 @@ test('still warns for post-contract verifier terminal records missing model meta
},
],
{
model_metadata_required_after: '2026-04-26T04:25:00Z',
input_file_count: 1,
artifact_selection_report: {
schema: 'workflows-weekly-metrics-artifact-selection/v1',
Expand All @@ -420,7 +427,27 @@ test('still warns for post-contract verifier terminal records missing model meta
assert.equal(report.verifier_model_compatibility.status, 'warning');
assert.equal(report.verifier_model_compatibility.missing_model_record_count, 1);
assert.equal(report.verifier_model_compatibility.legacy_missing_model_record_count, 0);
assert.deepEqual(report.enforcement.blockers, ['unsupported-verifier-model']);
assert.deepEqual(report.enforcement.blockers, ['missing-verifier-model-metadata']);
});

test('leaves verifier model metadata checks disabled unless explicitly configured', () => {
const report = summarizeTerminalDispositionCoverage([
{
schema: 'workflows-terminal-disposition/v1',
artifact_family: 'verifier-terminal-disposition',
source_type: 'pull-request',
source_id: '1877',
pr_number: 1877,
disposition: 'verifier-error',
verifier_mode: 'compare',
},
]);

assert.equal(report.status, 'pass');
assert.equal(report.verifier_model_compatibility.status, 'pass');
assert.equal(report.verifier_model_compatibility.model_metadata_contract.model_metadata_required, false);
assert.equal(report.verifier_model_compatibility.missing_model_record_count, 0);
assert.deepEqual(report.enforcement.blockers, []);
});

test('reads ndjson files and counts parse errors', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const {
buildInitialManifest,
finalizeManifest,
formatMarkdown,
safeArtifactPathSegment,
updateArtifactResult,
} = require('../weekly_metrics_download_manifest.js');

Expand Down Expand Up @@ -125,6 +126,24 @@ test('does not fall back to name when artifact id mismatches', () => {
);
});

test('sanitizes artifact names used in extraction paths', () => {
const manifest = buildInitialManifest({
...selection,
selected_artifacts: [
{
id: 44,
name: '../bad/name with spaces',
family: 'keepalive-metrics',
},
],
});

assert.equal(safeArtifactPathSegment('../bad/name with spaces'), '__bad_name_with_spaces');
assert.equal(manifest.artifacts[0].name, '../bad/name with spaces');
assert.equal(manifest.artifacts[0].artifact_dir, 'artifacts/__bad_name_with_spaces/44');
assert.equal(manifest.artifacts[0].zip_path, 'artifacts/__bad_name_with_spaces/44/44.zip');
});

test('formats human-visible markdown without replacing the JSON contract', () => {
const manifest = buildInitialManifest(selection);
updateArtifactResult(manifest, {
Expand Down
Loading
Loading