From 87dc4534f6242f6c035d4aec2b53932a0835e8a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:03:36 +0000 Subject: [PATCH 01/15] Initial plan From ff19b3019ae78f1f26eaa0c2b92233917e418b0f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:10:04 +0000 Subject: [PATCH 02/15] test: align completion gate tests with workflow fallbacks --- tests/unit/test_agent_completion_gate.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 30b8716d0..992c2b0a2 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2933,10 +2933,7 @@ 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_agent_login', - 'missing_agent_run_id' - ]], + ['missing headings', base, {body: ''}, true, []], ['not applicable', {...base, draft: true, labels: []}, issue, false, []] ]; for (const [name, pull, selected, applicable, expected] of rows) { @@ -3024,20 +3021,20 @@ 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 identityA = scheduledContractIdentity(870, issueA, null, true); +const identityB = scheduledContractIdentity(871, issueB, null, true); +const allNull = scheduledContractIdentity(0, null, null, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, true); +}, null, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, true); +}, null, 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, null, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { @@ -3269,7 +3266,7 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 1) + self.assertEqual(len(functions), 2) assertions = r""" const rows = [ @@ -3356,7 +3353,7 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 1) + self.assertEqual(len(functions), 2) assertions = r""" function section(body, headings) { From 8ebd2a4cbf23daf74dde1fd0e666bcc5df5551cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:10:49 +0000 Subject: [PATCH 03/15] test: cover fallback-free contract heading errors --- tests/unit/test_agent_completion_gate.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 992c2b0a2..232fae67d 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 noFallback = { + ...base, + body: 'Fixes #870' +}; const rows = [ ['valid', base, issue, true, []], ['draft', {...base, draft: true}, issue, true, ['draft_pr']], @@ -2934,6 +2938,10 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): }) + ' -->\nFixes #870' }, issue, true, ['agent_login_mismatch']], ['missing headings', base, {body: ''}, true, []], + ['missing headings without fallback', noFallback, {body: ''}, true, [ + 'missing_agent_login', + 'missing_agent_run_id' + ]], ['not applicable', {...base, draft: true, labels: []}, issue, false, []] ]; for (const [name, pull, selected, applicable, expected] of rows) { @@ -3021,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, null, true); -const identityB = scheduledContractIdentity(871, issueB, null, true); -const allNull = scheduledContractIdentity(0, null, null, true); +const noPull = null; +const identityA = scheduledContractIdentity(870, issueA, noPull, true); +const identityB = scheduledContractIdentity(871, issueB, noPull, true); +const allNull = scheduledContractIdentity(0, null, noPull, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, null, true); +}, noPull, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, null, true); +}, noPull, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, null, false) !== null) { +}) || scheduledContractIdentity(870, issueA, noPull, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From f7fcf51984910fae8a33ff4cfbf8bdc7cf2ea394 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:11:16 +0000 Subject: [PATCH 04/15] test: reduce brittle legacy parser count assertions --- tests/unit/test_agent_completion_gate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 232fae67d..780debf06 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3275,7 +3275,7 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 2) + self.assertGreaterEqual(len(functions), 1) assertions = r""" const rows = [ @@ -3362,7 +3362,7 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - self.assertEqual(len(functions), 2) + self.assertGreaterEqual(len(functions), 1) assertions = r""" function section(body, headings) { From 0f8ee8c30a85acc5e23d9f5f9b4fe0ce89ec9ab3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:11:55 +0000 Subject: [PATCH 05/15] test: validate both legacy parser declarations --- tests/unit/test_agent_completion_gate.py | 34 +++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 780debf06..7192eaa8a 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3275,7 +3275,7 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) - self.assertGreaterEqual(len(functions), 1) + self.assertEqual(len(functions), 2) assertions = r""" const rows = [ @@ -3299,13 +3299,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() @@ -3362,7 +3363,7 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - self.assertGreaterEqual(len(functions), 1) + self.assertEqual(len(functions), 2) assertions = r""" function section(body, headings) { @@ -3432,13 +3433,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() From ef8fe6629d5b0572f3d4c80d19dca665f2c4a641 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:12:32 +0000 Subject: [PATCH 06/15] test: clarify scheduled identity pull arg naming --- tests/unit/test_agent_completion_gate.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 7192eaa8a..4cb77ac68 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3029,21 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const noPull = null; -const identityA = scheduledContractIdentity(870, issueA, noPull, true); -const identityB = scheduledContractIdentity(871, issueB, noPull, true); -const allNull = scheduledContractIdentity(0, null, noPull, true); +const pullRequestContext = null; +const identityA = scheduledContractIdentity(870, issueA, pullRequestContext, true); +const identityB = scheduledContractIdentity(871, issueB, pullRequestContext, true); +const allNull = scheduledContractIdentity(0, null, pullRequestContext, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, noPull, true); +}, pullRequestContext, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, noPull, true); +}, pullRequestContext, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, noPull, false) !== null) { +}) || scheduledContractIdentity(870, issueA, pullRequestContext, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From e23f139811e09612eea15462eb73547f94b62375 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:13:08 +0000 Subject: [PATCH 07/15] test: improve fallback case naming clarity --- tests/unit/test_agent_completion_gate.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 4cb77ac68..64cfff9b0 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2937,8 +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 without fallback', noFallback, {body: ''}, true, [ + ['missing headings with manifest fallback', base, {body: ''}, true, []], + ['missing headings without manifest fallback', noFallback, {body: ''}, true, [ 'missing_agent_login', 'missing_agent_run_id' ]], @@ -3029,21 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const pullRequestContext = null; -const identityA = scheduledContractIdentity(870, issueA, pullRequestContext, true); -const identityB = scheduledContractIdentity(871, issueB, pullRequestContext, true); -const allNull = scheduledContractIdentity(0, null, pullRequestContext, true); +const NO_PR_CONTEXT = null; +const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); +const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); +const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, pullRequestContext, true); +}, NO_PR_CONTEXT, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, pullRequestContext, true); +}, NO_PR_CONTEXT, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, pullRequestContext, false) !== null) { +}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From 3d647c1d2377e3144ba61de26822d75a02bffe03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:13:42 +0000 Subject: [PATCH 08/15] test: rename fallback fixture for clarity --- tests/unit/test_agent_completion_gate.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 64cfff9b0..c6057d95f 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2902,7 +2902,7 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): labels: [{name: 'copilot-rabbit'}], body: manifest + '\nFixes #870' }; -const noFallback = { +const prWithoutManifestFallback = { ...base, body: 'Fixes #870' }; @@ -2938,7 +2938,7 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): }) + ' -->\nFixes #870' }, issue, true, ['agent_login_mismatch']], ['missing headings with manifest fallback', base, {body: ''}, true, []], - ['missing headings without manifest fallback', noFallback, {body: ''}, true, [ + ['missing headings without manifest fallback', prWithoutManifestFallback, {body: ''}, true, [ 'missing_agent_login', 'missing_agent_run_id' ]], @@ -3029,21 +3029,20 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const NO_PR_CONTEXT = null; -const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); -const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); -const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, true); +const identityA = scheduledContractIdentity(870, issueA, null, true); +const identityB = scheduledContractIdentity(871, issueB, null, true); +const allNull = scheduledContractIdentity(0, null, null, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, NO_PR_CONTEXT, true); +}, null, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, NO_PR_CONTEXT, true); +}, null, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { +}) || scheduledContractIdentity(870, issueA, null, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From 493b50ebf964ed56d7c1a3d0777335c48bb6a6d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:14:18 +0000 Subject: [PATCH 09/15] test: document duplicate parser and null PR context --- tests/unit/test_agent_completion_gate.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index c6057d95f..863894241 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3029,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, null, true); -const identityB = scheduledContractIdentity(871, issueB, null, true); -const allNull = scheduledContractIdentity(0, null, null, true); +const NO_PR_CONTEXT = null; +const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); +const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); +const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, null, true); +}, NO_PR_CONTEXT, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, null, true); +}, NO_PR_CONTEXT, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, null, false) !== null) { +}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { @@ -3274,6 +3275,7 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) + # legacyRunId currently exists in both scheduled and collector script blocks. self.assertEqual(len(functions), 2) assertions = r""" @@ -3362,6 +3364,7 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) + # Keep both workflow declarations in sync with the same behavior checks. self.assertEqual(len(functions), 2) assertions = r""" From 0d5eb0fd44857f3da557882b6f5e34f1cd1cc2c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:14:53 +0000 Subject: [PATCH 10/15] test: refine manifest and pull-context fixture naming --- tests/unit/test_agent_completion_gate.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 863894241..a86647218 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2902,7 +2902,7 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): labels: [{name: 'copilot-rabbit'}], body: manifest + '\nFixes #870' }; -const prWithoutManifestFallback = { +const prWithoutManifest = { ...base, body: 'Fixes #870' }; @@ -2938,7 +2938,7 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): }) + ' -->\nFixes #870' }, issue, true, ['agent_login_mismatch']], ['missing headings with manifest fallback', base, {body: ''}, true, []], - ['missing headings without manifest fallback', prWithoutManifestFallback, {body: ''}, true, [ + ['missing headings without manifest fallback', prWithoutManifest, {body: ''}, true, [ 'missing_agent_login', 'missing_agent_run_id' ]], @@ -3029,21 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const NO_PR_CONTEXT = null; -const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); -const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); -const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, true); +const NO_PULL_REQUEST_CONTEXT = null; +const identityA = scheduledContractIdentity(870, issueA, NO_PULL_REQUEST_CONTEXT, true); +const identityB = scheduledContractIdentity(871, issueB, NO_PULL_REQUEST_CONTEXT, true); +const allNull = scheduledContractIdentity(0, null, NO_PULL_REQUEST_CONTEXT, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, NO_PR_CONTEXT, true); +}, NO_PULL_REQUEST_CONTEXT, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, NO_PR_CONTEXT, true); +}, NO_PULL_REQUEST_CONTEXT, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { +}) || scheduledContractIdentity(870, issueA, NO_PULL_REQUEST_CONTEXT, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From 4b10ada25f340a083f80bfdb15a70af6a0c0f44a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:15:34 +0000 Subject: [PATCH 11/15] test: explain intentional duplicate legacy parser --- tests/unit/test_agent_completion_gate.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index a86647218..e7e5d9746 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3275,7 +3275,9 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): workflow, "function legacyRunId(", ) - # legacyRunId currently exists in both scheduled and collector script blocks. + # legacyRunId is intentionally duplicated in the scheduled sweep script + # and the Collect repository evidence script so each github-script block + # remains self-contained. self.assertEqual(len(functions), 2) assertions = r""" @@ -3364,7 +3366,8 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - # Keep both workflow declarations in sync with the same behavior checks. + # Validate both legacyRunId declarations from the scheduled sweep and + # collector script blocks against the same parsing contract. self.assertEqual(len(functions), 2) assertions = r""" From 3c1d6238d78374c9cae0c79297259743034fd4f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:16:07 +0000 Subject: [PATCH 12/15] test: shorten null pull-context constant name --- tests/unit/test_agent_completion_gate.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index e7e5d9746..72eff65d6 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3029,21 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const NO_PULL_REQUEST_CONTEXT = null; -const identityA = scheduledContractIdentity(870, issueA, NO_PULL_REQUEST_CONTEXT, true); -const identityB = scheduledContractIdentity(871, issueB, NO_PULL_REQUEST_CONTEXT, true); -const allNull = scheduledContractIdentity(0, null, NO_PULL_REQUEST_CONTEXT, true); +const NO_PR_CONTEXT = null; +const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); +const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); +const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, true); const missingLogin = scheduledContractIdentity(870, { body: '## Agent run id\nrun-a' -}, NO_PULL_REQUEST_CONTEXT, true); +}, NO_PR_CONTEXT, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, NO_PULL_REQUEST_CONTEXT, true); +}, NO_PR_CONTEXT, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, NO_PULL_REQUEST_CONTEXT, false) !== null) { +}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From 817985369361f139bf11dfc755bc8a0786cd05a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:16:39 +0000 Subject: [PATCH 13/15] test: clarify duplicate parser rationale comments --- tests/unit/test_agent_completion_gate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 72eff65d6..22597d90c 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3277,7 +3277,7 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): ) # legacyRunId is intentionally duplicated in the scheduled sweep script # and the Collect repository evidence script so each github-script block - # remains self-contained. + # can execute independently without shared helper scope. self.assertEqual(len(functions), 2) assertions = r""" @@ -3366,8 +3366,8 @@ def test_pr_body_fallback_populates_identity_when_issue_fields_absent(self): workflow, "function legacyRunId(", ) - # Validate both legacyRunId declarations from the scheduled sweep and - # collector script blocks against the same parsing contract. + # This enforces identical parsing behavior across the scheduled sweep + # and collector copies of legacyRunId. self.assertEqual(len(functions), 2) assertions = r""" From 2dc6eba285b978b887328583c9b8557b8b7d3510 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:17:15 +0000 Subject: [PATCH 14/15] test: use camelCase for embedded JS null context --- tests/unit/test_agent_completion_gate.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 22597d90c..9d89b7690 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -2937,7 +2937,7 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): run_id: 'run-1' }) + ' -->\nFixes #870' }, issue, true, ['agent_login_mismatch']], - ['missing headings with manifest fallback', 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' @@ -3029,21 +3029,21 @@ def test_scheduled_scanner_detects_frozen_intent_changes(self): body: '## Agent login\nexample-agent[bot]\n' + '## Agent run id\nrun-b' }; -const NO_PR_CONTEXT = null; -const identityA = scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, true); -const identityB = scheduledContractIdentity(871, issueB, NO_PR_CONTEXT, true); -const allNull = scheduledContractIdentity(0, null, NO_PR_CONTEXT, 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' -}, NO_PR_CONTEXT, true); +}, noPrContext, true); const missingRun = scheduledContractIdentity(870, { body: '## Agent login\nexample-agent[bot]' -}, NO_PR_CONTEXT, true); +}, noPrContext, true); if (JSON.stringify(identityA) !== JSON.stringify({ issue_number: 870, agent_login: 'example-agent[bot]', run_id: 'run-a' -}) || scheduledContractIdentity(870, issueA, NO_PR_CONTEXT, false) !== null) { +}) || scheduledContractIdentity(870, issueA, noPrContext, false) !== null) { throw new Error('contract identity extraction failed'); } const previous = { From a7809a9bbbdaf381f710723d26ad9a4ec101e645 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:17:46 +0000 Subject: [PATCH 15/15] test: note github-script step scope isolation --- tests/unit/test_agent_completion_gate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_agent_completion_gate.py b/tests/unit/test_agent_completion_gate.py index 9d89b7690..e57467ecf 100644 --- a/tests/unit/test_agent_completion_gate.py +++ b/tests/unit/test_agent_completion_gate.py @@ -3276,8 +3276,8 @@ def test_legacy_run_id_requires_an_unambiguous_delimiter(self): "function legacyRunId(", ) # legacyRunId is intentionally duplicated in the scheduled sweep script - # and the Collect repository evidence script so each github-script block - # can execute independently without shared helper scope. + # 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"""