From 288e5ae0845df74b57ce2431d87325ec242cf920 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:10:59 +0000 Subject: [PATCH 1/7] Add gh skill agent flag Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../setup/js/install_frontmatter_skills.cjs | 41 ++++++++++++++++--- .../js/install_frontmatter_skills.test.cjs | 38 +++++++++++++++-- pkg/workflow/activation_skills_step_test.go | 2 + .../compiler_activation_job_builder.go | 4 ++ 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/actions/setup/js/install_frontmatter_skills.cjs b/actions/setup/js/install_frontmatter_skills.cjs index b67aec9b659..1f8d5e47051 100644 --- a/actions/setup/js/install_frontmatter_skills.cjs +++ b/actions/setup/js/install_frontmatter_skills.cjs @@ -19,36 +19,60 @@ function parseSkillSpecs(rawSkills) { * @typedef {{args: string[]; displaySpec: string}} SkillInstallCommand */ +/** + * @param {string} engineID + * @returns {string} + */ +function getSkillInstallAgent(engineID) { + switch ((engineID || "").trim().toLowerCase()) { + case "copilot": + return "github-copilot"; + case "claude": + return "claude-code"; + case "gemini": + return "gemini-cli"; + case "codex": + case "antigravity": + case "opencode": + case "pi": + return (engineID || "").trim().toLowerCase(); + default: + return ""; + } +} + /** * @param {string} skillSpec * @param {string} skillsDst + * @param {string} skillInstallAgent * @returns {SkillInstallCommand} */ -function buildSkillInstallCommand(skillSpec, skillsDst) { +function buildSkillInstallCommand(skillSpec, skillsDst, skillInstallAgent = "") { const atIndex = skillSpec.lastIndexOf("@"); const hasPin = atIndex >= 0; const skillBase = hasPin ? skillSpec.slice(0, atIndex) : skillSpec; const skillRef = hasPin ? skillSpec.slice(atIndex + 1) : ""; const parts = skillBase.split("/"); const pinArgs = skillRef ? ["--pin", skillRef] : []; + const agentArgs = skillInstallAgent ? ["--agent", skillInstallAgent] : []; if (parts.length >= 3) { return { displaySpec: skillSpec, - args: ["skill", "install", `${parts[0]}/${parts[1]}`, parts.slice(2).join("/"), ...pinArgs, "--dir", skillsDst, "--force"], + args: ["skill", "install", `${parts[0]}/${parts[1]}`, parts.slice(2).join("/"), ...pinArgs, ...agentArgs, "--dir", skillsDst, "--force"], }; } if (parts.length === 2) { return { displaySpec: skillSpec, - args: ["skill", "install", skillBase, "--all", ...pinArgs, "--dir", skillsDst, "--force"], + args: ["skill", "install", skillBase, "--all", ...pinArgs, ...agentArgs, "--dir", skillsDst, "--force"], }; } return { displaySpec: skillSpec, - args: ["skill", "install", skillSpec, "--dir", skillsDst, "--force"], + args: ["skill", "install", skillSpec, ...agentArgs, "--dir", skillsDst, "--force"], }; } @@ -139,12 +163,17 @@ async function writeSkillSummary(skillDir, skills, installedSkillCount, failures async function main() { const skillDir = process.env.GH_AW_SKILL_DIR || ""; + const engineID = process.env.GH_AW_INFO_ENGINE_ID || ""; + const skillInstallAgent = getSkillInstallAgent(engineID); const skills = parseSkillSpecs(process.env.GH_AW_FRONTMATTER_SKILLS || ""); const skillsDst = path.join("/tmp/gh-aw", skillDir); fs.mkdirSync(skillsDst, { recursive: true }); core.info(`Installing frontmatter skills to ${skillsDst}`); + if (skillInstallAgent) { + core.info(`Installing frontmatter skills for gh skill agent ${skillInstallAgent}`); + } core.info("Existing skills at destination may be replaced (--force) to ensure pinned refs are up to date"); /** @type {Array<{skill: string; error: string}>} */ @@ -152,7 +181,7 @@ async function main() { for (const skillSpec of skills) { core.info(`Installing skill reference: ${skillSpec}`); - const command = buildSkillInstallCommand(skillSpec, skillsDst); + const command = buildSkillInstallCommand(skillSpec, skillsDst, skillInstallAgent); try { await exec.exec("gh", command.args); } catch (err) { @@ -171,4 +200,4 @@ async function main() { await writeSkillSummary(skillDir, skills, installedSkillCount, failures); } -module.exports = { main, parseSkillSpecs, buildSkillInstallCommand, countInstalledSkillFiles, appendSkillInstallFailure }; +module.exports = { main, parseSkillSpecs, getSkillInstallAgent, buildSkillInstallCommand, countInstalledSkillFiles, appendSkillInstallFailure }; diff --git a/actions/setup/js/install_frontmatter_skills.test.cjs b/actions/setup/js/install_frontmatter_skills.test.cjs index 81cf0eb679c..307c3347087 100644 --- a/actions/setup/js/install_frontmatter_skills.test.cjs +++ b/actions/setup/js/install_frontmatter_skills.test.cjs @@ -16,6 +16,7 @@ describe("install_frontmatter_skills", () => { beforeEach(() => { originalEnv = { GH_AW_SKILL_DIR: process.env.GH_AW_SKILL_DIR, + GH_AW_INFO_ENGINE_ID: process.env.GH_AW_INFO_ENGINE_ID, GH_AW_FRONTMATTER_SKILLS: process.env.GH_AW_FRONTMATTER_SKILLS, }; originalCore = global.core; @@ -41,6 +42,11 @@ describe("install_frontmatter_skills", () => { } else { process.env.GH_AW_SKILL_DIR = originalEnv.GH_AW_SKILL_DIR; } + if (originalEnv.GH_AW_INFO_ENGINE_ID === undefined) { + delete process.env.GH_AW_INFO_ENGINE_ID; + } else { + process.env.GH_AW_INFO_ENGINE_ID = originalEnv.GH_AW_INFO_ENGINE_ID; + } if (originalEnv.GH_AW_FRONTMATTER_SKILLS === undefined) { delete process.env.GH_AW_FRONTMATTER_SKILLS; } else { @@ -54,7 +60,19 @@ describe("install_frontmatter_skills", () => { }); it("splits repo-level and path-level skill specs into gh skill install arguments", () => { - expect(script.buildSkillInstallCommand("githubnext/skills@abc123", "/tmp/gh-aw/.claude/skills").args).toEqual(["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(script.buildSkillInstallCommand("githubnext/skills@abc123", "/tmp/gh-aw/.claude/skills", "claude-code").args).toEqual([ + "skill", + "install", + "githubnext/skills", + "--all", + "--pin", + "abc123", + "--agent", + "claude-code", + "--dir", + "/tmp/gh-aw/.claude/skills", + "--force", + ]); expect(script.buildSkillInstallCommand("githubnext/skills/review/security@abc123", "/tmp/gh-aw/.claude/skills").args).toEqual([ "skill", "install", @@ -68,21 +86,33 @@ describe("install_frontmatter_skills", () => { ]); }); + it("maps supported gh-aw engine IDs to gh skill agent values", () => { + expect(script.getSkillInstallAgent("copilot")).toBe("github-copilot"); + expect(script.getSkillInstallAgent("claude")).toBe("claude-code"); + expect(script.getSkillInstallAgent("codex")).toBe("codex"); + expect(script.getSkillInstallAgent("gemini")).toBe("gemini-cli"); + expect(script.getSkillInstallAgent("opencode")).toBe("opencode"); + expect(script.getSkillInstallAgent("pi")).toBe("pi"); + expect(script.getSkillInstallAgent("crush")).toBe(""); + expect(script.getSkillInstallAgent("")).toBe(""); + }); + it("omits --pin when the resolved skill spec is unpinned", () => { expect(script.buildSkillInstallCommand("githubnext/skills/review/security", "/tmp/gh-aw/.claude/skills").args).toEqual(["skill", "install", "githubnext/skills", "review/security", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); }); it("reads skill specs from the env var and installs them at runtime", async () => { process.env.GH_AW_SKILL_DIR = ".claude/skills"; + process.env.GH_AW_INFO_ENGINE_ID = "claude"; process.env.GH_AW_FRONTMATTER_SKILLS = ["githubnext/skills@abc123", "githubnext/skills/review/security@def456", "${{ inputs.skill_ref }}"].join("\n"); fs.mkdirSync("/tmp/gh-aw/.claude/skills/example", { recursive: true }); fs.writeFileSync("/tmp/gh-aw/.claude/skills/example/SKILL.md", "# test\n", "utf8"); await script.main(); - expect(global.exec.exec).toHaveBeenNthCalledWith(1, "gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); - expect(global.exec.exec).toHaveBeenNthCalledWith(2, "gh", ["skill", "install", "githubnext/skills", "review/security", "--pin", "def456", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); - expect(global.exec.exec).toHaveBeenNthCalledWith(3, "gh", ["skill", "install", "${{ inputs.skill_ref }}", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(1, "gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(2, "gh", ["skill", "install", "githubnext/skills", "review/security", "--pin", "def456", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(3, "gh", ["skill", "install", "${{ inputs.skill_ref }}", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); expect(global.core.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining("### Frontmatter skills installed")); expect(global.core.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining('["githubnext/skills@abc123","githubnext/skills/review/security@def456","${{ inputs.skill_ref }}"]')); }); diff --git a/pkg/workflow/activation_skills_step_test.go b/pkg/workflow/activation_skills_step_test.go index 84268ab2ee5..c7487ceb095 100644 --- a/pkg/workflow/activation_skills_step_test.go +++ b/pkg/workflow/activation_skills_step_test.go @@ -38,6 +38,7 @@ func TestBuildActivationJob_AddsFrontmatterSkillsInstallSteps(t *testing.T) { assert.Contains(t, steps, "ensure_gh_cli_min_version.sh", "expected gh upgrade step to delegate to ensure_gh_cli_min_version.sh") assert.Contains(t, steps, "Install frontmatter skill 1", "expected first frontmatter skill install step in activation job") assert.Contains(t, steps, "Install frontmatter skill 2", "expected second frontmatter skill install step in activation job") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"claude\"", "expected engine id env var for gh skill agent mapping") assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".claude/skills\"", "expected engine skill directory env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected first skill env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills/review/security@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected second skill env var") @@ -80,6 +81,7 @@ func TestBuildActivationJob_AddsPerSkillAuthSteps(t *testing.T) { steps := strings.Join(job.Steps, "") assert.Contains(t, steps, "GH_TOKEN: ${{ secrets.SKILL_PAT }}", "expected first skill install step to use per-skill github-token") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"copilot\"", "expected AI fallback engine id env var for gh skill agent mapping") assert.Contains(t, steps, "Generate GitHub App token for frontmatter skill 2", "expected app token mint step for second skill") assert.Contains(t, steps, "id: frontmatter-skill-app-token-2", "expected deterministic app token step id") assert.Contains(t, steps, "GH_TOKEN: ${{ steps.frontmatter-skill-app-token-2.outputs.token }}", "expected second skill install step to use minted app token") diff --git a/pkg/workflow/compiler_activation_job_builder.go b/pkg/workflow/compiler_activation_job_builder.go index 69402daf537..a89cbc41121 100644 --- a/pkg/workflow/compiler_activation_job_builder.go +++ b/pkg/workflow/compiler_activation_job_builder.go @@ -538,6 +538,9 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext if ctx.data.EngineConfig != nil { engineID = ctx.data.EngineConfig.ID } + if engineID == "" && ctx.data.AI != "" { + engineID = ctx.data.AI + } skillDir := GetEngineSkillDir(engineID) ctx.steps = append(ctx.steps, " - name: Upgrade gh CLI for frontmatter skills\n") @@ -569,6 +572,7 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext ctx.steps = append(ctx.steps, fmt.Sprintf(" - name: Install frontmatter skill %d\n", i+1)) ctx.steps = append(ctx.steps, " env:\n") ctx.steps = append(ctx.steps, fmt.Sprintf(" GH_TOKEN: %s\n", tokenExpr)) + ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_INFO_ENGINE_ID", engineID)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_SKILL_DIR", skillDir)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_FRONTMATTER_SKILLS", skillRef.Skill)) ctx.steps = append(ctx.steps, fmt.Sprintf(" uses: %s\n", getCachedActionPin("actions/github-script", ctx.data))) From a54544aaa58b1a0075dd936e0b0e516604fa97a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:11:45 +0000 Subject: [PATCH 2/7] Expand gh skill agent tests Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../setup/js/install_frontmatter_skills.test.cjs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/actions/setup/js/install_frontmatter_skills.test.cjs b/actions/setup/js/install_frontmatter_skills.test.cjs index 307c3347087..55688c0ad64 100644 --- a/actions/setup/js/install_frontmatter_skills.test.cjs +++ b/actions/setup/js/install_frontmatter_skills.test.cjs @@ -84,6 +84,19 @@ describe("install_frontmatter_skills", () => { "/tmp/gh-aw/.claude/skills", "--force", ]); + expect(script.buildSkillInstallCommand("githubnext/skills/review/security@abc123", "/tmp/gh-aw/.claude/skills", "claude-code").args).toEqual([ + "skill", + "install", + "githubnext/skills", + "review/security", + "--pin", + "abc123", + "--agent", + "claude-code", + "--dir", + "/tmp/gh-aw/.claude/skills", + "--force", + ]); }); it("maps supported gh-aw engine IDs to gh skill agent values", () => { @@ -91,6 +104,7 @@ describe("install_frontmatter_skills", () => { expect(script.getSkillInstallAgent("claude")).toBe("claude-code"); expect(script.getSkillInstallAgent("codex")).toBe("codex"); expect(script.getSkillInstallAgent("gemini")).toBe("gemini-cli"); + expect(script.getSkillInstallAgent("antigravity")).toBe("antigravity"); expect(script.getSkillInstallAgent("opencode")).toBe("opencode"); expect(script.getSkillInstallAgent("pi")).toBe("pi"); expect(script.getSkillInstallAgent("crush")).toBe(""); From 8eac2de7c5b41c5cfaa56ad54e80d8b46efd0523 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:29:56 +0000 Subject: [PATCH 3/7] Plan review-driven engine env fix Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/mattpocock-skills-reviewer.lock.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/mattpocock-skills-reviewer.lock.yml b/.github/workflows/mattpocock-skills-reviewer.lock.yml index 8eab732c87d..57ed757b4f9 100644 --- a/.github/workflows/mattpocock-skills-reviewer.lock.yml +++ b/.github/workflows/mattpocock-skills-reviewer.lock.yml @@ -295,6 +295,7 @@ jobs: - name: Install frontmatter skill 1 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/diagnosing-bugs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -307,6 +308,7 @@ jobs: - name: Install frontmatter skill 2 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/tdd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -319,6 +321,7 @@ jobs: - name: Install frontmatter skill 3 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/improve-codebase-architecture@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -331,6 +334,7 @@ jobs: - name: Install frontmatter skill 4 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/grill-with-docs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -343,6 +347,7 @@ jobs: - name: Install frontmatter skill 5 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/to-prd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -355,6 +360,7 @@ jobs: - name: Install frontmatter skill 6 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/codebase-design@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -367,6 +373,7 @@ jobs: - name: Install frontmatter skill 7 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/domain-modeling@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 From 9ee73504f8be97cee7f781efc325f95e8518736c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:35:12 +0000 Subject: [PATCH 4/7] Move gh skill agent mapping into engine metadata Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../setup/js/install_frontmatter_skills.cjs | 27 ++----------------- .../js/install_frontmatter_skills.test.cjs | 19 +++++-------- pkg/workflow/activation_skills_step_test.go | 25 +++++++++++++++++ pkg/workflow/agentic_engine.go | 9 +++++++ pkg/workflow/antigravity_engine.go | 9 ++++--- pkg/workflow/claude_engine.go | 9 ++++--- pkg/workflow/codex_engine.go | 9 ++++--- .../compiler_activation_job_builder.go | 14 +++++----- pkg/workflow/copilot_engine.go | 9 ++++--- pkg/workflow/gemini_engine.go | 9 ++++--- pkg/workflow/opencode_engine.go | 9 ++++--- pkg/workflow/pi_engine.go | 9 ++++--- 12 files changed, 86 insertions(+), 71 deletions(-) diff --git a/actions/setup/js/install_frontmatter_skills.cjs b/actions/setup/js/install_frontmatter_skills.cjs index 1f8d5e47051..ec0a5240f36 100644 --- a/actions/setup/js/install_frontmatter_skills.cjs +++ b/actions/setup/js/install_frontmatter_skills.cjs @@ -19,28 +19,6 @@ function parseSkillSpecs(rawSkills) { * @typedef {{args: string[]; displaySpec: string}} SkillInstallCommand */ -/** - * @param {string} engineID - * @returns {string} - */ -function getSkillInstallAgent(engineID) { - switch ((engineID || "").trim().toLowerCase()) { - case "copilot": - return "github-copilot"; - case "claude": - return "claude-code"; - case "gemini": - return "gemini-cli"; - case "codex": - case "antigravity": - case "opencode": - case "pi": - return (engineID || "").trim().toLowerCase(); - default: - return ""; - } -} - /** * @param {string} skillSpec * @param {string} skillsDst @@ -163,8 +141,7 @@ async function writeSkillSummary(skillDir, skills, installedSkillCount, failures async function main() { const skillDir = process.env.GH_AW_SKILL_DIR || ""; - const engineID = process.env.GH_AW_INFO_ENGINE_ID || ""; - const skillInstallAgent = getSkillInstallAgent(engineID); + const skillInstallAgent = process.env.GH_AW_GH_SKILL_AGENT_NAME || ""; const skills = parseSkillSpecs(process.env.GH_AW_FRONTMATTER_SKILLS || ""); const skillsDst = path.join("/tmp/gh-aw", skillDir); @@ -200,4 +177,4 @@ async function main() { await writeSkillSummary(skillDir, skills, installedSkillCount, failures); } -module.exports = { main, parseSkillSpecs, getSkillInstallAgent, buildSkillInstallCommand, countInstalledSkillFiles, appendSkillInstallFailure }; +module.exports = { main, parseSkillSpecs, buildSkillInstallCommand, countInstalledSkillFiles, appendSkillInstallFailure }; diff --git a/actions/setup/js/install_frontmatter_skills.test.cjs b/actions/setup/js/install_frontmatter_skills.test.cjs index 55688c0ad64..8e460dd3f11 100644 --- a/actions/setup/js/install_frontmatter_skills.test.cjs +++ b/actions/setup/js/install_frontmatter_skills.test.cjs @@ -17,6 +17,7 @@ describe("install_frontmatter_skills", () => { originalEnv = { GH_AW_SKILL_DIR: process.env.GH_AW_SKILL_DIR, GH_AW_INFO_ENGINE_ID: process.env.GH_AW_INFO_ENGINE_ID, + GH_AW_GH_SKILL_AGENT_NAME: process.env.GH_AW_GH_SKILL_AGENT_NAME, GH_AW_FRONTMATTER_SKILLS: process.env.GH_AW_FRONTMATTER_SKILLS, }; originalCore = global.core; @@ -47,6 +48,11 @@ describe("install_frontmatter_skills", () => { } else { process.env.GH_AW_INFO_ENGINE_ID = originalEnv.GH_AW_INFO_ENGINE_ID; } + if (originalEnv.GH_AW_GH_SKILL_AGENT_NAME === undefined) { + delete process.env.GH_AW_GH_SKILL_AGENT_NAME; + } else { + process.env.GH_AW_GH_SKILL_AGENT_NAME = originalEnv.GH_AW_GH_SKILL_AGENT_NAME; + } if (originalEnv.GH_AW_FRONTMATTER_SKILLS === undefined) { delete process.env.GH_AW_FRONTMATTER_SKILLS; } else { @@ -99,18 +105,6 @@ describe("install_frontmatter_skills", () => { ]); }); - it("maps supported gh-aw engine IDs to gh skill agent values", () => { - expect(script.getSkillInstallAgent("copilot")).toBe("github-copilot"); - expect(script.getSkillInstallAgent("claude")).toBe("claude-code"); - expect(script.getSkillInstallAgent("codex")).toBe("codex"); - expect(script.getSkillInstallAgent("gemini")).toBe("gemini-cli"); - expect(script.getSkillInstallAgent("antigravity")).toBe("antigravity"); - expect(script.getSkillInstallAgent("opencode")).toBe("opencode"); - expect(script.getSkillInstallAgent("pi")).toBe("pi"); - expect(script.getSkillInstallAgent("crush")).toBe(""); - expect(script.getSkillInstallAgent("")).toBe(""); - }); - it("omits --pin when the resolved skill spec is unpinned", () => { expect(script.buildSkillInstallCommand("githubnext/skills/review/security", "/tmp/gh-aw/.claude/skills").args).toEqual(["skill", "install", "githubnext/skills", "review/security", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); }); @@ -118,6 +112,7 @@ describe("install_frontmatter_skills", () => { it("reads skill specs from the env var and installs them at runtime", async () => { process.env.GH_AW_SKILL_DIR = ".claude/skills"; process.env.GH_AW_INFO_ENGINE_ID = "claude"; + process.env.GH_AW_GH_SKILL_AGENT_NAME = "claude-code"; process.env.GH_AW_FRONTMATTER_SKILLS = ["githubnext/skills@abc123", "githubnext/skills/review/security@def456", "${{ inputs.skill_ref }}"].join("\n"); fs.mkdirSync("/tmp/gh-aw/.claude/skills/example", { recursive: true }); fs.writeFileSync("/tmp/gh-aw/.claude/skills/example/SKILL.md", "# test\n", "utf8"); diff --git a/pkg/workflow/activation_skills_step_test.go b/pkg/workflow/activation_skills_step_test.go index c7487ceb095..b21b3883733 100644 --- a/pkg/workflow/activation_skills_step_test.go +++ b/pkg/workflow/activation_skills_step_test.go @@ -39,6 +39,7 @@ func TestBuildActivationJob_AddsFrontmatterSkillsInstallSteps(t *testing.T) { assert.Contains(t, steps, "Install frontmatter skill 1", "expected first frontmatter skill install step in activation job") assert.Contains(t, steps, "Install frontmatter skill 2", "expected second frontmatter skill install step in activation job") assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"claude\"", "expected engine id env var for gh skill agent mapping") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"claude-code\"", "expected gh skill agent env var for claude") assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".claude/skills\"", "expected engine skill directory env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected first skill env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills/review/security@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected second skill env var") @@ -82,11 +83,35 @@ func TestBuildActivationJob_AddsPerSkillAuthSteps(t *testing.T) { steps := strings.Join(job.Steps, "") assert.Contains(t, steps, "GH_TOKEN: ${{ secrets.SKILL_PAT }}", "expected first skill install step to use per-skill github-token") assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"copilot\"", "expected AI fallback engine id env var for gh skill agent mapping") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"github-copilot\"", "expected gh skill agent env var for copilot fallback") assert.Contains(t, steps, "Generate GitHub App token for frontmatter skill 2", "expected app token mint step for second skill") assert.Contains(t, steps, "id: frontmatter-skill-app-token-2", "expected deterministic app token step id") assert.Contains(t, steps, "GH_TOKEN: ${{ steps.frontmatter-skill-app-token-2.outputs.token }}", "expected second skill install step to use minted app token") } +func TestBuildActivationJob_DefaultsSkillInstallEngineToCopilot(t *testing.T) { + compiler := NewCompiler(WithVersion("dev")) + compiler.SetActionMode(ActionModeDev) + + data := &WorkflowData{ + Name: "skills-workflow", + On: `"on": + workflow_dispatch:`, + Skills: []string{ + "githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6", + }, + } + + job, err := compiler.buildActivationJob(data, false, "", "skills.lock.yml") + require.NoError(t, err) + require.NotNil(t, job) + + steps := strings.Join(job.Steps, "") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"copilot\"", "expected default engine id env var for frontmatter skill installs") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"github-copilot\"", "expected default gh skill agent env var for frontmatter skill installs") + assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".github/skills\"", "expected default engine skill directory env var") +} + func TestBuildActivationJob_AppIgnoreIfMissingFallsBackToActivationToken(t *testing.T) { compiler := NewCompiler(WithVersion("dev")) compiler.SetActionMode(ActionModeDev) diff --git a/pkg/workflow/agentic_engine.go b/pkg/workflow/agentic_engine.go index 70d5f46ca3d..38b8900bc31 100644 --- a/pkg/workflow/agentic_engine.go +++ b/pkg/workflow/agentic_engine.go @@ -100,6 +100,10 @@ type Engine interface { // IsExperimental returns true if this engine is experimental IsExperimental() bool + + // GetGHSkillAgentName returns the gh skill --agent value for this engine. + // Returns an empty string when gh skill install does not support the engine. + GetGHSkillAgentName() string } // EngineCapabilities captures optional engine features. @@ -314,6 +318,7 @@ type BaseEngine struct { displayName string description string experimental bool + ghSkillAgentName string capabilities EngineCapabilities dedicatedLLMGatewayPort int } @@ -334,6 +339,10 @@ func (e *BaseEngine) IsExperimental() bool { return e.experimental } +func (e *BaseEngine) GetGHSkillAgentName() string { + return e.ghSkillAgentName +} + func (e *BaseEngine) GetCapabilities() EngineCapabilities { return e.capabilities } diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 1b304e3d483..6af5458e6b1 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -19,10 +19,11 @@ type AntigravityEngine struct { func NewAntigravityEngine() *AntigravityEngine { return &AntigravityEngine{ BaseEngine: BaseEngine{ - id: "antigravity", - displayName: "Antigravity CLI", - description: "Antigravity CLI with headless mode and LLM gateway support", - experimental: true, + id: "antigravity", + displayName: "Antigravity CLI", + description: "Antigravity CLI with headless mode and LLM gateway support", + experimental: true, + ghSkillAgentName: "antigravity", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index bc6eed2a31c..4d6cbd6c3b6 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -22,10 +22,11 @@ type ClaudeEngine struct { func NewClaudeEngine() *ClaudeEngine { return &ClaudeEngine{ BaseEngine: BaseEngine{ - id: "claude", - displayName: "Claude Code", - description: "Uses Claude Code with full MCP tool support and allow-listing", - experimental: false, + id: "claude", + displayName: "Claude Code", + description: "Uses Claude Code with full MCP tool support and allow-listing", + experimental: false, + ghSkillAgentName: "claude-code", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // Claude supports max-turns feature diff --git a/pkg/workflow/codex_engine.go b/pkg/workflow/codex_engine.go index 31d2d0b998d..e49d5b37ce1 100644 --- a/pkg/workflow/codex_engine.go +++ b/pkg/workflow/codex_engine.go @@ -50,10 +50,11 @@ type CodexEngine struct { func NewCodexEngine() *CodexEngine { return &CodexEngine{ BaseEngine: BaseEngine{ - id: "codex", - displayName: "Codex", - description: "Uses OpenAI Codex CLI with MCP server support", - experimental: false, + id: "codex", + displayName: "Codex", + description: "Uses OpenAI Codex CLI with MCP server support", + experimental: false, + ghSkillAgentName: "codex", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // AWF max-turns is supported for Codex runs diff --git a/pkg/workflow/compiler_activation_job_builder.go b/pkg/workflow/compiler_activation_job_builder.go index a89cbc41121..b0ba23b87c8 100644 --- a/pkg/workflow/compiler_activation_job_builder.go +++ b/pkg/workflow/compiler_activation_job_builder.go @@ -534,14 +534,15 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext return nil } - engineID := "" - if ctx.data.EngineConfig != nil { - engineID = ctx.data.EngineConfig.ID - } - if engineID == "" && ctx.data.AI != "" { - engineID = ctx.data.AI + engineID := strings.TrimSpace(ResolveEngineID(ctx.data)) + if engineID == "" { + engineID = string(constants.DefaultEngine) } skillDir := GetEngineSkillDir(engineID) + skillInstallAgentName := "" + if engine, err := GetGlobalEngineRegistry().GetEngine(strings.ToLower(engineID)); err == nil { + skillInstallAgentName = engine.GetGHSkillAgentName() + } ctx.steps = append(ctx.steps, " - name: Upgrade gh CLI for frontmatter skills\n") ctx.steps = append(ctx.steps, fmt.Sprintf(" run: bash \"${RUNNER_TEMP}/gh-aw/actions/ensure_gh_cli_min_version.sh\" \"%s\"\n", constants.GhSkillsMinVersion)) @@ -573,6 +574,7 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext ctx.steps = append(ctx.steps, " env:\n") ctx.steps = append(ctx.steps, fmt.Sprintf(" GH_TOKEN: %s\n", tokenExpr)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_INFO_ENGINE_ID", engineID)) + ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_GH_SKILL_AGENT_NAME", skillInstallAgentName)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_SKILL_DIR", skillDir)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_FRONTMATTER_SKILLS", skillRef.Skill)) ctx.steps = append(ctx.steps, fmt.Sprintf(" uses: %s\n", getCachedActionPin("actions/github-script", ctx.data))) diff --git a/pkg/workflow/copilot_engine.go b/pkg/workflow/copilot_engine.go index 0acfdeabe9c..b131c23d9fa 100644 --- a/pkg/workflow/copilot_engine.go +++ b/pkg/workflow/copilot_engine.go @@ -34,10 +34,11 @@ func NewCopilotEngine() *CopilotEngine { copilotLog.Print("Creating new Copilot engine instance") return &CopilotEngine{ BaseEngine: BaseEngine{ - id: "copilot", - displayName: "GitHub Copilot CLI", - description: "Uses GitHub Copilot CLI with MCP server support", - experimental: false, + id: "copilot", + displayName: "GitHub Copilot CLI", + description: "Uses GitHub Copilot CLI with MCP server support", + experimental: false, + ghSkillAgentName: "github-copilot", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // AWF max-turns is supported for Copilot runs diff --git a/pkg/workflow/gemini_engine.go b/pkg/workflow/gemini_engine.go index e2e98cc958d..ad5e54a1cba 100644 --- a/pkg/workflow/gemini_engine.go +++ b/pkg/workflow/gemini_engine.go @@ -19,10 +19,11 @@ type GeminiEngine struct { func NewGeminiEngine() *GeminiEngine { return &GeminiEngine{ BaseEngine: BaseEngine{ - id: "gemini", - displayName: "Google Gemini CLI", - description: "Google Gemini CLI with headless mode and LLM gateway support", - experimental: false, + id: "gemini", + displayName: "Google Gemini CLI", + description: "Google Gemini CLI with headless mode and LLM gateway support", + experimental: false, + ghSkillAgentName: "gemini-cli", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, diff --git a/pkg/workflow/opencode_engine.go b/pkg/workflow/opencode_engine.go index 35753a2f876..b427883d192 100644 --- a/pkg/workflow/opencode_engine.go +++ b/pkg/workflow/opencode_engine.go @@ -20,10 +20,11 @@ func NewOpenCodeEngine() *OpenCodeEngine { return &OpenCodeEngine{ UniversalLLMConsumerEngine: UniversalLLMConsumerEngine{ BaseEngine: BaseEngine{ - id: "opencode", - displayName: "OpenCode", - description: "OpenCode CLI with headless mode and multi-provider LLM support", - experimental: true, + id: "opencode", + displayName: "OpenCode", + description: "OpenCode CLI with headless mode and multi-provider LLM support", + experimental: true, + ghSkillAgentName: "opencode", capabilities: EngineCapabilities{ ToolsAllowlist: false, MaxTurns: true, diff --git a/pkg/workflow/pi_engine.go b/pkg/workflow/pi_engine.go index ce43c83c24e..069a660c78e 100644 --- a/pkg/workflow/pi_engine.go +++ b/pkg/workflow/pi_engine.go @@ -34,10 +34,11 @@ type PiEngine struct { func NewPiEngine() *PiEngine { return &PiEngine{ BaseEngine: BaseEngine{ - id: "pi", - displayName: "Pi", - description: "Pi AI coding agent (experimental)", - experimental: true, + id: "pi", + displayName: "Pi", + description: "Pi AI coding agent (experimental)", + experimental: true, + ghSkillAgentName: "pi", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, From a5d33dbf3eaa448224fcf710e92017cf7b2067eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:41:23 +0000 Subject: [PATCH 5/7] Refresh generated skill install agent env Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/mattpocock-skills-reviewer.lock.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/mattpocock-skills-reviewer.lock.yml b/.github/workflows/mattpocock-skills-reviewer.lock.yml index 57ed757b4f9..3f016644d9a 100644 --- a/.github/workflows/mattpocock-skills-reviewer.lock.yml +++ b/.github/workflows/mattpocock-skills-reviewer.lock.yml @@ -296,6 +296,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/diagnosing-bugs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -309,6 +310,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/tdd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -322,6 +324,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/improve-codebase-architecture@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -335,6 +338,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/grill-with-docs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -348,6 +352,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/to-prd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -361,6 +366,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/codebase-design@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -374,6 +380,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/domain-modeling@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 From 526bb23f1e0cc0a4a5d0e59d54e3886b296ca813 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:53:37 +0000 Subject: [PATCH 6/7] Fix legacy skill artifact engine fallback Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- .../js/install_frontmatter_skills.test.cjs | 9 ++++++++ pkg/workflow/activation_skills_step_test.go | 23 +++++++++++++++++++ .../compiler_activation_job_builder.go | 18 ++++++++------- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/actions/setup/js/install_frontmatter_skills.test.cjs b/actions/setup/js/install_frontmatter_skills.test.cjs index 8e460dd3f11..48c38921fcf 100644 --- a/actions/setup/js/install_frontmatter_skills.test.cjs +++ b/actions/setup/js/install_frontmatter_skills.test.cjs @@ -126,6 +126,15 @@ describe("install_frontmatter_skills", () => { expect(global.core.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining('["githubnext/skills@abc123","githubnext/skills/review/security@def456","${{ inputs.skill_ref }}"]')); }); + it("omits --agent when no gh skill agent name is provided", async () => { + process.env.GH_AW_SKILL_DIR = ".claude/skills"; + process.env.GH_AW_FRONTMATTER_SKILLS = "githubnext/skills@abc123"; + + await script.main(); + + expect(global.exec.exec).toHaveBeenCalledWith("gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + }); + it("records failures without throwing when skill install fails", async () => { process.env.GH_AW_SKILL_DIR = ".claude/skills"; process.env.GH_AW_FRONTMATTER_SKILLS = "bad/repo@abc123"; diff --git a/pkg/workflow/activation_skills_step_test.go b/pkg/workflow/activation_skills_step_test.go index b21b3883733..c265080a956 100644 --- a/pkg/workflow/activation_skills_step_test.go +++ b/pkg/workflow/activation_skills_step_test.go @@ -112,6 +112,29 @@ func TestBuildActivationJob_DefaultsSkillInstallEngineToCopilot(t *testing.T) { assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".github/skills\"", "expected default engine skill directory env var") } +func TestBuildActivationJob_UsesLegacyAIEngineForSkillArtifactPath(t *testing.T) { + compiler := NewCompiler(WithVersion("dev")) + compiler.SetActionMode(ActionModeDev) + + data := &WorkflowData{ + Name: "skills-workflow", + On: `"on": + workflow_dispatch:`, + AI: "claude", + Skills: []string{ + "githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6", + }, + } + + job, err := compiler.buildActivationJob(data, false, "", "skills.lock.yml") + require.NoError(t, err) + require.NotNil(t, job) + + steps := strings.Join(job.Steps, "") + assert.Contains(t, steps, "/tmp/gh-aw/.claude/skills", "expected activation artifact upload to include the legacy ai engine skill directory") + assert.NotContains(t, steps, "/tmp/gh-aw/.github/skills", "expected legacy ai workflows to avoid the default copilot skill directory") +} + func TestBuildActivationJob_AppIgnoreIfMissingFallsBackToActivationToken(t *testing.T) { compiler := NewCompiler(WithVersion("dev")) compiler.SetActionMode(ActionModeDev) diff --git a/pkg/workflow/compiler_activation_job_builder.go b/pkg/workflow/compiler_activation_job_builder.go index b0ba23b87c8..ad915b260fa 100644 --- a/pkg/workflow/compiler_activation_job_builder.go +++ b/pkg/workflow/compiler_activation_job_builder.go @@ -50,6 +50,14 @@ type activationJobBuildContext struct { activationInferredPerms map[PermissionScope]PermissionLevel } +func resolveActivationEngineID(workflowData *WorkflowData) string { + engineID := strings.TrimSpace(ResolveEngineID(workflowData)) + if engineID == "" { + return string(constants.DefaultEngine) + } + return engineID +} + // newActivationJobBuildContext initializes activation-job state with setup, aw_info, and base outputs. func (c *Compiler) newActivationJobBuildContext( data *WorkflowData, @@ -534,10 +542,7 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext return nil } - engineID := strings.TrimSpace(ResolveEngineID(ctx.data)) - if engineID == "" { - engineID = string(constants.DefaultEngine) - } + engineID := resolveActivationEngineID(ctx.data) skillDir := GetEngineSkillDir(engineID) skillInstallAgentName := "" if engine, err := GetGlobalEngineRegistry().GetEngine(strings.ToLower(engineID)); err == nil { @@ -846,10 +851,7 @@ func (c *Compiler) addActivationArtifactUploadStep(ctx *activationJobBuildContex ctx.steps = append(ctx.steps, " /tmp/gh-aw/aw-prompts/prompt-import-tree.json\n") ctx.steps = append(ctx.steps, " /tmp/gh-aw/"+constants.GithubRateLimitsFilename+"\n") ctx.steps = append(ctx.steps, " /tmp/gh-aw/base\n") - engineID := "" - if ctx.data.EngineConfig != nil { - engineID = ctx.data.EngineConfig.ID - } + engineID := resolveActivationEngineID(ctx.data) // Include the engine-specific sub-agent staging directory only when inline agents are enabled. if isFeatureEnabled(constants.FeatureFlag("inline-agents"), ctx.data) { subAgentDir := GetEngineSubAgentDir(engineID) From a22cd69e45a8e4e83f5200407c5960582dd26424 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:56:58 +0000 Subject: [PATCH 7/7] Document activation engine resolution helper Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- pkg/workflow/compiler_activation_job_builder.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/workflow/compiler_activation_job_builder.go b/pkg/workflow/compiler_activation_job_builder.go index ad915b260fa..fe678aeee14 100644 --- a/pkg/workflow/compiler_activation_job_builder.go +++ b/pkg/workflow/compiler_activation_job_builder.go @@ -50,6 +50,9 @@ type activationJobBuildContext struct { activationInferredPerms map[PermissionScope]PermissionLevel } +// resolveActivationEngineID resolves the workflow engine for activation-time paths, +// defaulting to the repository-wide default engine when frontmatter leaves it unset. +// This keeps skill installation and activation artifact uploads on the same engine-specific directory. func resolveActivationEngineID(workflowData *WorkflowData) string { engineID := strings.TrimSpace(ResolveEngineID(workflowData)) if engineID == "" {