@@ -42,7 +42,7 @@ afterEach(() => {
4242
4343describe ( "workspace subagent installer" , ( ) => {
4444 it ( "renders Claude agent definitions with yaml frontmatter" , async ( ) => {
45- const content = testExports . renderClaudeAgent ( subagent ) ;
45+ const content = testExports . renderMarkdownAgent ( "claude" , subagent ) ;
4646
4747 expect ( content ) . toContain ( "---\n" ) ;
4848 expect ( content ) . toContain ( "name: test-writer" ) ;
@@ -76,9 +76,10 @@ describe("workspace subagent installer", () => {
7676 const installed = await ensureSubagents ( worktree , "claude" , [ subagent ] ) ;
7777
7878 expect ( installed ) . toBe ( true ) ;
79- expect ( readFileSync ( join ( worktree , ".claude/agents/test-writer.md" ) , "utf-8" ) ) . toBe ( testExports . renderClaudeAgent ( subagent ) ) ;
79+ expect ( readFileSync ( join ( worktree , ".claude/agents/test-writer.md" ) , "utf-8" ) ) . toBe ( testExports . renderMarkdownAgent ( "claude" , subagent ) ) ;
8080 expect ( readFileSync ( join ( worktree , ".gitignore" ) , "utf-8" ) ) . toContain ( ".claude/agents/" ) ;
8181 expect ( readFileSync ( join ( worktree , ".gitignore" ) , "utf-8" ) ) . toContain ( ".codex/agents/" ) ;
82+ expect ( readFileSync ( join ( worktree , ".gitignore" ) , "utf-8" ) ) . toContain ( ".gemini/agents/" ) ;
8283 } ) ;
8384
8485 it ( "writes Codex subagents and keeps identical files stable" , async ( ) => {
@@ -101,9 +102,44 @@ describe("workspace subagent installer", () => {
101102 expect ( statSync ( filePath ) . mtimeMs ) . toBe ( firstMtime ) ;
102103 } ) ;
103104
105+ it ( "writes Gemini subagents as project markdown agent definitions" , async ( ) => {
106+ const worktree = makeWorktree ( ) ;
107+ const geminiSubagent = { ...subagent , runtime : "gemini" as const , model : "gemini-3-pro" } ;
108+
109+ expect ( await ensureSubagents ( worktree , "gemini" , [ geminiSubagent ] ) ) . toBe ( true ) ;
110+ const content = readFileSync ( join ( worktree , ".gemini/agents/test-writer.md" ) , "utf-8" ) ;
111+
112+ expect ( content ) . toBe ( testExports . renderMarkdownAgent ( "gemini" , geminiSubagent ) ) ;
113+ expect ( content ) . toContain ( "name: test-writer" ) ;
114+ expect ( content ) . not . toContain ( "model:" ) ;
115+ } ) ;
116+
117+ it ( "writes Copilot subagents through Claude-compatible project markdown agent definitions" , async ( ) => {
118+ const worktree = makeWorktree ( ) ;
119+ const copilotSubagent = { ...subagent , runtime : "copilot" as const , model : "gpt-5.2" } ;
120+
121+ expect ( await ensureSubagents ( worktree , "copilot" , [ copilotSubagent ] ) ) . toBe ( true ) ;
122+ const content = readFileSync ( join ( worktree , ".claude/agents/test-writer.md" ) , "utf-8" ) ;
123+
124+ expect ( content ) . toBe ( testExports . renderMarkdownAgent ( "copilot" , copilotSubagent ) ) ;
125+ expect ( content ) . toContain ( "name: test-writer" ) ;
126+ expect ( content ) . not . toContain ( "model:" ) ;
127+ } ) ;
128+
129+ it ( "does not leak Claude model frontmatter into Gemini or Copilot agent files" , async ( ) => {
130+ const worktree = makeWorktree ( ) ;
131+ const claudeWorker = { ...subagent , runtime : "claude" as const , model : "claude-opus-4-6" } ;
132+
133+ expect ( await ensureSubagents ( worktree , "gemini" , [ claudeWorker ] ) ) . toBe ( true ) ;
134+ expect ( await ensureSubagents ( worktree , "copilot" , [ claudeWorker ] ) ) . toBe ( true ) ;
135+
136+ expect ( readFileSync ( join ( worktree , ".gemini/agents/test-writer.md" ) , "utf-8" ) ) . not . toContain ( "model:" ) ;
137+ expect ( readFileSync ( join ( worktree , ".claude/agents/test-writer.md" ) , "utf-8" ) ) . not . toContain ( "model:" ) ;
138+ } ) ;
139+
104140 it ( "returns false when the runtime does not support local subagent files" , async ( ) => {
105141 const worktree = makeWorktree ( ) ;
106142
107- await expect ( ensureSubagents ( worktree , "gemini " , [ subagent ] ) ) . resolves . toBe ( false ) ;
143+ await expect ( ensureSubagents ( worktree , "hermes " , [ subagent ] ) ) . resolves . toBe ( false ) ;
108144 } ) ;
109145} ) ;
0 commit comments