From fd23a35e002a5b9a5770d0484583a8cc1cbc0478 Mon Sep 17 00:00:00 2001 From: Chuck Lantz Date: Mon, 20 Jul 2026 14:21:19 -0700 Subject: [PATCH 1/3] Allow co-author to be specified by the platform --- src/client.ts | 10 ++++++++++ src/git.ts | 30 +++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 7a5000f..a05c4dd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -500,6 +500,16 @@ export interface JobDetails { branch_name?: string; commit_login: string; commit_email: string; + /** + * Login for the `Co-authored-by` trailer on agent commits. Distinct from the + * commit author (`commit_login`): by default the agent authors the commit and + * the user is credited as co-author, but under act-as-user the roles swap so + * the user authors and the agent is the co-author. Optional for backward + * compatibility with platforms that do not populate it. + */ + commit_coauthor_login?: string; + /** Email for the `Co-authored-by` trailer. See {@link commit_coauthor_login}. */ + commit_coauthor_email?: string; mcp_proxy_url?: string; /** Model selected by the platform for this run. Present when model selection is enabled. */ selected_model?: string; diff --git a/src/git.ts b/src/git.ts index 30d768c..a7ae3a3 100644 --- a/src/git.ts +++ b/src/git.ts @@ -16,6 +16,13 @@ import { existsSync } from "fs"; const DEFAULT_CLONE_DIR = "/tmp/workspace"; +// Environment variables carrying the platform-served commit co-author, set by +// the ccav3 app from job details. Used to append a `Co-authored-by` trailer to +// commits this SDK creates (the finalize safety-net commit), mirroring the +// trailer the runtime emits for report_progress commits. +const COAUTHOR_LOGIN_ENV = "GITHUB_COPILOT_COMMIT_COAUTHOR_LOGIN"; +const COAUTHOR_EMAIL_ENV = "GITHUB_COPILOT_COMMIT_COAUTHOR_EMAIL"; + // ============================================================================= // Helpers // ============================================================================= @@ -33,6 +40,27 @@ function branchExistsOnRemote(repoLocation: string, branchName: string): boolean return output.length > 0; } +/** + * Appends a `Co-authored-by` trailer built from the platform-served commit + * co-author (exposed via GITHUB_COPILOT_COMMIT_COAUTHOR_LOGIN/GITHUB_COPILOT_COMMIT_COAUTHOR_EMAIL) + * to the commit message. The served email is used verbatim so it matches the + * trailer the runtime emits and the server-side signing check. Returns the + * message unchanged when the variables are unset or the trailer is already + * present. + */ +function withCoAuthorTrailer(commitMessage: string): string { + const login = process.env[COAUTHOR_LOGIN_ENV]; + const email = process.env[COAUTHOR_EMAIL_ENV]; + if (!login || !email) { + return commitMessage; + } + const trailer = `Co-authored-by: ${login} <${email}>`; + if (commitMessage.includes(trailer)) { + return commitMessage; + } + return `${commitMessage.trimEnd()}\n\n${trailer}`; +} + // ============================================================================= // Types // ============================================================================= @@ -266,7 +294,7 @@ export function commitAndPush(repoLocation: string, commitMessage: string): Comm if (status) { hadChanges = true; git(["add", "."], repoLocation); - git(["commit", "-m", commitMessage], repoLocation); + git(["commit", "-m", withCoAuthorTrailer(commitMessage)], repoLocation); } pushWithRebaseFallback(repoLocation); From 80079bef7bc4233f34f115da0796b425893d03fe Mon Sep 17 00:00:00 2001 From: Chuck Lantz Date: Mon, 20 Jul 2026 21:31:31 -0500 Subject: [PATCH 2/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/git.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/git.ts b/src/git.ts index a7ae3a3..6e28a07 100644 --- a/src/git.ts +++ b/src/git.ts @@ -55,10 +55,12 @@ function withCoAuthorTrailer(commitMessage: string): string { return commitMessage; } const trailer = `Co-authored-by: ${login} <${email}>`; - if (commitMessage.includes(trailer)) { + const normalizedMessage = commitMessage.trimEnd(); + const lastParagraph = normalizedMessage.split(/\r?\n(?:\r?\n)+/).pop() ?? ""; + if (lastParagraph.split(/\r?\n/).includes(trailer)) { return commitMessage; } - return `${commitMessage.trimEnd()}\n\n${trailer}`; + return `${normalizedMessage}\n\n${trailer}`; } // ============================================================================= From 07f001835d9f79f320d6c2da4c6a34e18c6509d3 Mon Sep 17 00:00:00 2001 From: Chuck Lantz Date: Mon, 20 Jul 2026 19:36:14 -0700 Subject: [PATCH 3/3] Fix MCP push path --- src/git.ts | 2 +- src/mcp-server.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/git.ts b/src/git.ts index 6e28a07..0c3f709 100644 --- a/src/git.ts +++ b/src/git.ts @@ -48,7 +48,7 @@ function branchExistsOnRemote(repoLocation: string, branchName: string): boolean * message unchanged when the variables are unset or the trailer is already * present. */ -function withCoAuthorTrailer(commitMessage: string): string { +export function withCoAuthorTrailer(commitMessage: string): string { const login = process.env[COAUTHOR_LOGIN_ENV]; const email = process.env[COAUTHOR_EMAIL_ENV]; if (!login || !email) { diff --git a/src/mcp-server.ts b/src/mcp-server.ts index c5f7ec1..d2967c9 100644 --- a/src/mcp-server.ts +++ b/src/mcp-server.ts @@ -25,7 +25,7 @@ import { appendFileSync } from "fs"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; -import { commitAndPush } from "./git.js"; +import { commitAndPush, withCoAuthorTrailer } from "./git.js"; import type { PlatformClient } from "./client.js"; // ============================================================================= @@ -135,7 +135,7 @@ async function executeReportProgress( if (status) { execFileSync("git", ["add", "."], { cwd: config.workingDir }); - execFileSync("git", ["commit", "-m", commitMessage], { cwd: config.workingDir }); + execFileSync("git", ["commit", "-m", withCoAuthorTrailer(commitMessage)], { cwd: config.workingDir }); log("git commit complete (local only)", { message: commitMessage }); results.push(`Committed locally: ${commitMessage}`); } else {