diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 30b8716d0..e57467ecf 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2902,6 +2902,10 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): labels: [{name: 'copilot-rabbit'}], body: manifest + '\nFixes #870' }; +const prWithoutManifest = { + ...base, + body: 'Fixes #870' +}; const rows = [ ['valid', base, issue, true, []], ['draft', {...base, draft: true}, issue, true, ['draft_pr']], @@ -2933,7 +2937,8 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): run_id: 'run-1' }) + ' -->\nFixes #870' }, issue, true, ['agent_login_mismatch']], - ['missing headings', base, {body: ''}, true, [ + ['missing headings use parsed manifest fallback', base, {body: ''}, true, []], + ['missing headings without manifest fallback', prWithoutManifest, {body: ''}, true, [ 'missing_agent_login', 'missing_agent_run_id' ]], @@ -3024,20 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const identityA = scheduledContractIdentity(870, issueA, true); -const identityB = scheduledContractIdentity(871, issueB, true); -const allNull = scheduledContractIdentity(0, null, true); +const noPrContext = null; +const identityA = scheduledContractIdentity(870, issueA, noPrContext, true); +const identityB = scheduledContractIdentity(871, issueB, noPrContext, true); +const allNull = scheduledContractIdentity(0, null, noPrContext, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, true); +}, noPrContext, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, true); +}, noPrContext, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, false) !== null) { +}) || scheduledContractIdentity(870, issueA, noPrContext, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { @@ -3269,7 +3275,10 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 1) + # legacyRunId is intentionally duplicated in the scheduled sweep script + # and the Collect repository evidence script because github-script steps + # execute in isolated runtimes and cannot share helper scope. + self.assertEqual(len(functions), 2) assertions = r""" const rows = [ @@ -3293,13 +3302,14 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): } } """ - completed = subprocess.run( - ["node", "-e", functions[0] + assertions], - check=False, - capture_output=True, - text=True, - ) - self.assertEqual(completed.returncode, 0, completed.stderr) + for function in functions: + completed = subprocess.run( + ["node", "-e", function + assertions], + check=False, + capture_output=True, + text=True, + ) + self.assertEqual(completed.returncode, 0, completed.stderr) def test_extract_run_id_duplicate_parser_matches_legacy(self): workflow = self._workflow() @@ -3356,7 +3366,9 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 1) + # This enforces identical parsing behavior across the scheduled sweep + # and collector copies of legacyRunId. + self.assertEqual(len(functions), 2) assertions = r""" function section(body, headings) { @@ -3426,13 +3438,14 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): throw new Error('issue login should win over fallbacks: ' + fromIssue.login); } """ - completed = subprocess.run( - ["node", "-e", functions[0] + assertions], - check=False, - capture_output=True, - text=True, - ) - self.assertEqual(completed.returncode, 0, completed.stderr) + for function in functions: + completed = subprocess.run( + ["node", "-e", function + assertions], + check=False, + capture_output=True, + text=True, + ) + self.assertEqual(completed.returncode, 0, completed.stderr) def test_mismatch_errors_require_manifest_match(self): workflow = self._workflow()