From 354a56565024f668f6b933c2b5397f79b8c10dea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 08:53:47 +0000 Subject: [PATCH 1/2] Initial plan From 9ac779ee24082f66427742b9a181637ab6bcb9fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 09:06:01 +0000 Subject: [PATCH 2/2] Fix work queue delivery verification with submission metadata Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/work_queue_delivery.cjs | 2 +- actions/setup/js/work_queue_delivery.test.cjs | 55 ++++++++++--------- .../work_queue_native_creation_delivery.cjs | 2 + ...rk_queue_native_creation_delivery.test.cjs | 19 ++++++- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/actions/setup/js/work_queue_delivery.cjs b/actions/setup/js/work_queue_delivery.cjs index 73e59a25899..5074193ba15 100644 --- a/actions/setup/js/work_queue_delivery.cjs +++ b/actions/setup/js/work_queue_delivery.cjs @@ -486,7 +486,7 @@ async function verifyBuiltinDeliveryOutput(options) { if (["create_discussion", "create_pull_request"].includes(message.type)) return require("./work_queue_native_creation_delivery.cjs").verifyNativeCreationDelivery(options); // Updating branches still requires its own pinned commit/tree verifier. if (message.type === "update_pull_request") return unverified("delivery.builtin.pinned_verifier_required"); - const verifiedFields = new Set(["type", "claim_handle", "claim_id", "work_id", "repo", "item_number", "issue_number", "pull_request_number", "temporary_id", ...(BUILTIN_EFFECT_FIELDS[message.type] || [])]); + const verifiedFields = new Set(["type", "output_id", "depends-on", "claim_handle", "claim_id", "work_id", "repo", "item_number", "issue_number", "pull_request_number", "temporary_id", ...(BUILTIN_EFFECT_FIELDS[message.type] || [])]); if (Object.keys(message).some(field => !verifiedFields.has(field))) return unverified("delivery.builtin.undeclared_fields"); if (!result || result.staged || !github?.rest || message.data !== undefined || message.duplicate_of !== undefined) return unverified("delivery.builtin.readback_unavailable", { result_present: !!result, staged: !!result?.staged, client_present: !!github?.rest, data_present: message.data !== undefined, duplicate: message.duplicate_of !== undefined }); diff --git a/actions/setup/js/work_queue_delivery.test.cjs b/actions/setup/js/work_queue_delivery.test.cjs index e1b411fadcf..9ab28b1639d 100644 --- a/actions/setup/js/work_queue_delivery.test.cjs +++ b/actions/setup/js/work_queue_delivery.test.cjs @@ -41,35 +41,38 @@ describe("historical diagnostic delivery contracts", () => { for (const legacy of ["missing_tool", "missing_data"]) { const canonical = `report_${legacy}`; - it(`matches ${legacy} contracts and messages canonically without rewriting immutable Work`, async () => { - for (const contractType of [legacy, canonical]) { - const original = assignment([ - { type: "create_issue", min: 1, max: 1 }, - { type: contractType, min: 1, max: 1 }, - ]); - const before = JSON.stringify(original); - const beforeDigest = digest(original); - expect(validateDeliveryContract(original.claims[0].work.effect_contract)).toBe(original.claims[0].work.effect_contract); - for (const messageType of [legacy, canonical]) { - const messages = [Object.freeze({ type: "create_issue", repo: "owner/repo" }), Object.freeze({ type: messageType })]; - const delivered = await deliver(original, messages, { - verifyOutput: verifyBuiltinDeliveryOutput, - github: { - rest: { - repos: { get: async () => ({ data: { id: 7, full_name: "owner/repo" } }) }, - issues: { get: async () => ({ data: { id: 142, number: 42, html_url: "https://github.com/owner/repo/issues/42" } }) }, + it.each([{}, { output_id: "so_xbzi2dhGSY-3" }, { "depends-on": "so_priorOutput1" }, { output_id: "so_xbzi2dhGSY-3", "depends-on": "so_priorOutput1" }])( + `matches ${legacy} contracts and messages canonically without rewriting immutable Work with metadata %j`, + async metadata => { + for (const contractType of [legacy, canonical]) { + const original = assignment([ + { type: "create_issue", min: 1, max: 1 }, + { type: contractType, min: 1, max: 1 }, + ]); + const before = JSON.stringify(original); + const beforeDigest = digest(original); + expect(validateDeliveryContract(original.claims[0].work.effect_contract)).toBe(original.claims[0].work.effect_contract); + for (const messageType of [legacy, canonical]) { + const messages = [Object.freeze({ type: "create_issue", repo: "owner/repo", ...metadata }), Object.freeze({ type: messageType })]; + const delivered = await deliver(original, messages, { + verifyOutput: verifyBuiltinDeliveryOutput, + github: { + rest: { + repos: { get: async () => ({ data: { id: 7, full_name: "owner/repo" } }) }, + issues: { get: async () => ({ data: { id: 142, number: 42, html_url: "https://github.com/owner/repo/issues/42" } }) }, + }, }, - }, - }); - expect(delivered.verification).toBe("verified"); - expect(delivered.disposition).toBe("complete"); - expect(delivered.descriptor.outputs[1]).toEqual({ type: canonical, effect: "none" }); - expect(messages[1].type).toBe(messageType); - expect(JSON.stringify(original)).toBe(before); - expect(digest(original)).toBe(beforeDigest); + }); + expect(delivered.verification).toBe("verified"); + expect(delivered.disposition).toBe("complete"); + expect(delivered.descriptor.outputs[1]).toEqual({ type: canonical, effect: "none" }); + expect(messages[1].type).toBe(messageType); + expect(JSON.stringify(original)).toBe(before); + expect(digest(original)).toBe(beforeDigest); + } } } - }); + ); it(`shares cardinality across ${legacy} and ${canonical} messages`, async () => { const messages = [{ type: legacy }, { type: canonical }]; diff --git a/actions/setup/js/work_queue_native_creation_delivery.cjs b/actions/setup/js/work_queue_native_creation_delivery.cjs index 3268c756d58..4bec4c1a588 100644 --- a/actions/setup/js/work_queue_native_creation_delivery.cjs +++ b/actions/setup/js/work_queue_native_creation_delivery.cjs @@ -323,6 +323,8 @@ async function verifyNativeCreationDelivery(options) { } const fields = new Set([ "type", + "output_id", + "depends-on", "claim_handle", "claim_id", "work_id", diff --git a/actions/setup/js/work_queue_native_creation_delivery.test.cjs b/actions/setup/js/work_queue_native_creation_delivery.test.cjs index 84050b35328..78b15c5d1c9 100644 --- a/actions/setup/js/work_queue_native_creation_delivery.test.cjs +++ b/actions/setup/js/work_queue_native_creation_delivery.test.cjs @@ -610,8 +610,13 @@ describe("native creation Claim delivery", () => { } }); - it.each(["create_discussion", "create_pull_request"])("settles %s through the actual manager verifier and publishes a protected Result", async type => { + it.each( + ["create_discussion", "create_pull_request"].flatMap(type => + [{}, { output_id: "so_xbzi2dhGSY-3" }, { "depends-on": "so_priorOutput1" }, { output_id: "so_xbzi2dhGSY-3", "depends-on": "so_priorOutput1" }].map(metadata => ({ type, metadata })) + ) + )("settles $type with submission metadata $metadata through the actual manager verifier and publishes a protected Result", async ({ type, metadata }) => { const f = fixture(type); + Object.assign(f.message, metadata); await f.execute(async () => { await f.capture(); expect(closeClaimEffectChannel()).toBeDefined(); @@ -624,6 +629,18 @@ describe("native creation Claim delivery", () => { expect(f.queue.state.works.get(f.member.work_id).barrier).toBe("verified"); }); + it.each(["create_discussion", "create_pull_request"])("rejects undeclared %s fields even with submission metadata", async type => { + const f = fixture(type); + Object.assign(f.message, { output_id: "so_xbzi2dhGSY-3", "depends-on": "so_priorOutput1", unexpected_transport_field: "untrusted" }); + await f.execute(async () => { + await f.capture(); + expect((await f.settle()).verification).toBe("unknown"); + }); + expect(f.client.graphql).not.toHaveBeenCalled(); + expect(f.client.rest.pulls.get).not.toHaveBeenCalled(); + expect(f.queue.state.works.get(f.member.work_id).barrier).toBe("pending"); + }); + it("settles the enriched PR message emitted by the safe-output transport", async () => { const f = fixture("create_pull_request"); Object.assign(f.message, { head_repo: REPOSITORY, base_branch: "main", base_commit: BASE });