@markjaquith/agency 1.11.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +302 -113
  2. package/cli.ts +123 -415
  3. package/index.ts +1 -1
  4. package/package.json +12 -17
  5. package/skills/agency/SKILL.md +258 -0
  6. package/src/cli.test.ts +290 -0
  7. package/src/commands/description.test.ts +103 -0
  8. package/src/commands/epic.test.ts +103 -0
  9. package/src/commands/epic.ts +101 -0
  10. package/src/commands/init.test.ts +42 -290
  11. package/src/commands/init.ts +15 -123
  12. package/src/commands/phase.ts +120 -0
  13. package/src/commands/pr.test.ts +19 -170
  14. package/src/commands/pr.ts +23 -179
  15. package/src/commands/repo.test.ts +80 -0
  16. package/src/commands/repo.ts +83 -0
  17. package/src/commands/status.test.ts +35 -477
  18. package/src/commands/status.ts +24 -213
  19. package/src/commands/task-phase.test.ts +206 -0
  20. package/src/commands/task.ts +83 -1285
  21. package/src/commands/validate.test.ts +91 -0
  22. package/src/commands/validate.ts +50 -0
  23. package/src/commands/work.test.ts +172 -419
  24. package/src/commands/work.ts +47 -166
  25. package/src/services/EpicService.test.ts +71 -0
  26. package/src/services/EpicService.ts +135 -0
  27. package/src/services/FileSystemService.ts +61 -92
  28. package/src/services/PhaseService.ts +323 -0
  29. package/src/services/PullRequestService.test.ts +386 -0
  30. package/src/services/PullRequestService.ts +143 -0
  31. package/src/services/RepositoryService.test.ts +106 -0
  32. package/src/services/RepositoryService.ts +159 -0
  33. package/src/services/TaskPhaseService.test.ts +217 -0
  34. package/src/services/TaskService.ts +192 -0
  35. package/src/services/WorkbaseService.test.ts +446 -0
  36. package/src/services/WorkbaseService.ts +493 -0
  37. package/src/services/WorktreeService.test.ts +599 -0
  38. package/src/services/WorktreeService.ts +357 -0
  39. package/src/test-utils.ts +41 -438
  40. package/src/types.ts +1 -215
  41. package/src/utils/command.ts +1 -5
  42. package/src/utils/effect.test.ts +24 -0
  43. package/src/utils/effect.ts +3 -273
  44. package/src/utils/process.test.ts +0 -15
  45. package/src/utils/process.ts +1 -60
  46. package/src/workbase/frontmatter.test.ts +50 -0
  47. package/src/workbase/frontmatter.ts +77 -0
  48. package/src/workbase/repository-reference.test.ts +25 -0
  49. package/src/workbase/repository-reference.ts +18 -0
  50. package/src/workbase/schemas.test.ts +146 -0
  51. package/src/workbase/schemas.ts +78 -0
  52. package/src/workbase/worktree-command.test.ts +61 -0
  53. package/src/workbase/worktree-command.ts +52 -0
  54. package/src/commands/base.test.ts +0 -198
  55. package/src/commands/base.ts +0 -198
  56. package/src/commands/clean.test.ts +0 -299
  57. package/src/commands/clean.ts +0 -274
  58. package/src/commands/completions.test.ts +0 -51
  59. package/src/commands/completions.ts +0 -308
  60. package/src/commands/emit.integration.test.ts +0 -549
  61. package/src/commands/emit.test.ts +0 -576
  62. package/src/commands/emit.ts +0 -700
  63. package/src/commands/emitted.test.ts +0 -226
  64. package/src/commands/emitted.ts +0 -57
  65. package/src/commands/loop.test.ts +0 -621
  66. package/src/commands/loop.ts +0 -406
  67. package/src/commands/merge.integration.test.ts +0 -195
  68. package/src/commands/merge.test.ts +0 -246
  69. package/src/commands/merge.ts +0 -244
  70. package/src/commands/pull.test.ts +0 -395
  71. package/src/commands/pull.ts +0 -205
  72. package/src/commands/push.test.ts +0 -518
  73. package/src/commands/push.ts +0 -434
  74. package/src/commands/rebase.test.ts +0 -521
  75. package/src/commands/rebase.ts +0 -232
  76. package/src/commands/save.test.ts +0 -247
  77. package/src/commands/save.ts +0 -162
  78. package/src/commands/source.test.ts +0 -195
  79. package/src/commands/source.ts +0 -72
  80. package/src/commands/switch.test.ts +0 -194
  81. package/src/commands/switch.ts +0 -84
  82. package/src/commands/task-branching.test.ts +0 -633
  83. package/src/commands/task-continue.test.ts +0 -311
  84. package/src/commands/task-edit.test.ts +0 -235
  85. package/src/commands/task-main.test.ts +0 -1066
  86. package/src/commands/task-squash.test.ts +0 -266
  87. package/src/commands/tasks.test.ts +0 -391
  88. package/src/commands/tasks.ts +0 -161
  89. package/src/commands/template-delete.test.ts +0 -178
  90. package/src/commands/template-delete.ts +0 -98
  91. package/src/commands/template-list.test.ts +0 -135
  92. package/src/commands/template-list.ts +0 -87
  93. package/src/commands/template-view.test.ts +0 -158
  94. package/src/commands/template-view.ts +0 -86
  95. package/src/commands/template.test.ts +0 -32
  96. package/src/commands/template.ts +0 -96
  97. package/src/commands/use.test.ts +0 -87
  98. package/src/commands/use.ts +0 -97
  99. package/src/constants.ts +0 -10
  100. package/src/errors.ts +0 -17
  101. package/src/schemas.ts +0 -33
  102. package/src/services/AgencyMetadataService.ts +0 -311
  103. package/src/services/ClaudeService.test.ts +0 -184
  104. package/src/services/ClaudeService.ts +0 -91
  105. package/src/services/ConfigService.ts +0 -115
  106. package/src/services/FilterRepoService.ts +0 -164
  107. package/src/services/FormatterService.test.ts +0 -432
  108. package/src/services/FormatterService.ts +0 -219
  109. package/src/services/GitService.ts +0 -1183
  110. package/src/services/MockFilterRepoService.ts +0 -140
  111. package/src/services/OpencodeService.ts +0 -263
  112. package/src/services/PromptService.ts +0 -183
  113. package/src/services/TemplateService.ts +0 -81
  114. package/src/types/native-exec.d.ts +0 -8
  115. package/src/utils/colors.ts +0 -178
  116. package/src/utils/git-path.ts +0 -6
  117. package/src/utils/glob.test.ts +0 -161
  118. package/src/utils/glob.ts +0 -78
  119. package/src/utils/paths.ts +0 -51
  120. package/src/utils/pr-branch.test.ts +0 -376
  121. package/src/utils/pr-branch.ts +0 -508
  122. package/src/utils/spinner.test.ts +0 -45
  123. package/src/utils/spinner.ts +0 -96
  124. package/src/utils/task-parser.test.ts +0 -172
  125. package/src/utils/task-parser.ts +0 -93
  126. package/templates/AGENCY.md +0 -22
  127. package/templates/AGENTS.md +0 -11
  128. package/templates/CLAUDE.md +0 -3
  129. package/templates/TASK.md +0 -5
  130. package/templates/opencode.json +0 -4
@@ -1,246 +0,0 @@
1
- import { test, expect, describe, beforeEach, afterEach } from "bun:test"
2
- import { join } from "path"
3
- import { merge } from "./merge"
4
- import { emit } from "./emit"
5
- import { task } from "./task"
6
- import {
7
- createTempDir,
8
- cleanupTempDir,
9
- initGitRepo,
10
- initAgency,
11
- getGitOutput,
12
- getCurrentBranch,
13
- createCommit,
14
- checkoutBranch,
15
- createBranch,
16
- addAndCommit,
17
- setupRemote,
18
- deleteBranch,
19
- runTestEffect,
20
- } from "../test-utils"
21
-
22
- describe("merge command", () => {
23
- let tempDir: string
24
- let originalCwd: string
25
-
26
- beforeEach(async () => {
27
- tempDir = await createTempDir()
28
- originalCwd = process.cwd()
29
- process.chdir(tempDir)
30
-
31
- // Set config path to non-existent file to use defaults
32
- process.env.AGENCY_CONFIG_PATH = join(tempDir, "non-existent-config.json")
33
- // Set config dir to temp dir to avoid picking up user's config files
34
- process.env.AGENCY_CONFIG_DIR = await createTempDir()
35
-
36
- // Initialize git repo with main branch (already includes initial commit)
37
- await initGitRepo(tempDir)
38
-
39
- // Set up origin for git-filter-repo
40
- await setupRemote(tempDir, "origin", tempDir)
41
-
42
- // Create a source branch (with agency-- prefix per new default config)
43
- await createBranch(tempDir, "agency--feature")
44
-
45
- // Initialize AGENTS.md on feature branch
46
- await initAgency(tempDir, "test")
47
-
48
- await runTestEffect(task({ silent: true, fromCurrent: true }))
49
-
50
- // Ensure agency.json has baseBranch set (task should auto-detect it, but ensure it's there)
51
- const agencyJsonPath = join(tempDir, "agency.json")
52
- const agencyJson = await Bun.file(agencyJsonPath).json()
53
- if (!agencyJson.baseBranch) {
54
- agencyJson.baseBranch = "origin/main"
55
- await Bun.write(
56
- agencyJsonPath,
57
- JSON.stringify(agencyJson, null, 2) + "\n",
58
- )
59
- }
60
-
61
- await addAndCommit(tempDir, "AGENTS.md agency.json", "Add AGENTS.md")
62
-
63
- // Create another commit on feature branch
64
- await createCommit(tempDir, "Feature work")
65
- })
66
-
67
- afterEach(async () => {
68
- process.chdir(originalCwd)
69
- delete process.env.AGENCY_CONFIG_PATH
70
- if (process.env.AGENCY_CONFIG_DIR) {
71
- await cleanupTempDir(process.env.AGENCY_CONFIG_DIR)
72
- delete process.env.AGENCY_CONFIG_DIR
73
- }
74
- await cleanupTempDir(tempDir)
75
- })
76
-
77
- describe("error handling", () => {
78
- test("throws error when not in a git repository", async () => {
79
- const nonGitDir = await createTempDir()
80
- process.chdir(nonGitDir)
81
-
82
- await expect(runTestEffect(merge({ silent: true }))).rejects.toThrow(
83
- "Not in a git repository",
84
- )
85
-
86
- await cleanupTempDir(nonGitDir)
87
- })
88
-
89
- test("throws error if base branch does not exist locally", async () => {
90
- // Create emit branch (skipFilter for speed since we're testing error handling)
91
- await runTestEffect(emit({ silent: true, skipFilter: true }))
92
-
93
- // Delete main branch (the base)
94
- await checkoutBranch(tempDir, "feature")
95
- await deleteBranch(tempDir, "main", true)
96
-
97
- // Try to merge - should fail
98
- await expect(
99
- runTestEffect(merge({ silent: true, skipFilter: true })),
100
- ).rejects.toThrow("does not exist locally")
101
- })
102
- })
103
-
104
- describe("silent mode", () => {
105
- test("silent flag suppresses output", async () => {
106
- const logs: string[] = []
107
- const originalLog = console.log
108
- console.log = (...args: any[]) => logs.push(args.join(" "))
109
-
110
- await runTestEffect(merge({ silent: true, skipFilter: true }))
111
-
112
- console.log = originalLog
113
-
114
- expect(logs.length).toBe(0)
115
- })
116
- })
117
-
118
- describe("squash merge", () => {
119
- test("performs squash merge when --squash flag is set", async () => {
120
- // We're on feature branch (source)
121
- const currentBranch = await getCurrentBranch(tempDir)
122
- expect(currentBranch).toBe("agency--feature")
123
-
124
- // Run merge with squash flag (skipFilter for speed, we're testing squash behavior)
125
- await runTestEffect(
126
- merge({ silent: true, squash: true, skipFilter: true }),
127
- )
128
-
129
- // Should be on main branch after merge
130
- const afterMergeBranch = await getCurrentBranch(tempDir)
131
- expect(afterMergeBranch).toBe("main")
132
-
133
- // Check that changes are staged but not committed
134
- const status = await getGitOutput(tempDir, ["status", "--porcelain"])
135
-
136
- // Staged changes should be present (indicated by status codes in first column)
137
- expect(status.trim().length).toBeGreaterThan(0)
138
-
139
- // Get the log to verify no merge commit was created
140
- const log = await getGitOutput(tempDir, ["log", "--oneline", "-5"])
141
-
142
- // Should not contain a merge commit message
143
- expect(log).not.toContain("Merge branch")
144
- })
145
-
146
- test("performs regular merge when --squash flag is not set", async () => {
147
- // We're on feature branch (source)
148
- const currentBranch = await getCurrentBranch(tempDir)
149
- expect(currentBranch).toBe("agency--feature")
150
-
151
- // Run merge without squash flag (skipFilter for speed, we're testing merge behavior)
152
- await runTestEffect(
153
- merge({ silent: true, squash: false, skipFilter: true }),
154
- )
155
-
156
- // Should be on main branch after merge
157
- const afterMergeBranch = await getCurrentBranch(tempDir)
158
- expect(afterMergeBranch).toBe("main")
159
-
160
- // With regular merge (not squash), there should be no staged changes
161
- const status = await getGitOutput(tempDir, ["status", "--porcelain"])
162
-
163
- // No staged changes - everything should be committed
164
- expect(status.trim().length).toBe(0)
165
-
166
- // Get the log to verify commits were included
167
- const log = await getGitOutput(tempDir, ["log", "--oneline", "-5"])
168
-
169
- // Should contain the feature work commit (regular merge includes all commits)
170
- expect(log).toContain("Feature work")
171
- })
172
- })
173
-
174
- describe("push flag", () => {
175
- test("pushes base branch to origin when --push flag is set", async () => {
176
- // We're on feature branch (source)
177
- const currentBranch = await getCurrentBranch(tempDir)
178
- expect(currentBranch).toBe("agency--feature")
179
-
180
- // Get the current commit on main before merge
181
- await checkoutBranch(tempDir, "main")
182
- const beforeCommit = (
183
- await getGitOutput(tempDir, ["rev-parse", "HEAD"])
184
- ).trim()
185
-
186
- // Go back to feature branch
187
- await checkoutBranch(tempDir, "agency--feature")
188
-
189
- // Run merge with push flag (skipFilter for speed, we're testing push behavior)
190
- await runTestEffect(merge({ silent: true, push: true, skipFilter: true }))
191
-
192
- // Should be on main branch after merge
193
- const afterMergeBranch = await getCurrentBranch(tempDir)
194
- expect(afterMergeBranch).toBe("main")
195
-
196
- // Get the current commit on main after merge
197
- const afterCommit = (
198
- await getGitOutput(tempDir, ["rev-parse", "HEAD"])
199
- ).trim()
200
-
201
- // The commit should have changed (merge happened)
202
- expect(afterCommit).not.toBe(beforeCommit)
203
-
204
- // Verify that origin/main points to the same commit as local main
205
- const originMainCommit = (
206
- await getGitOutput(tempDir, ["rev-parse", "origin/main"])
207
- ).trim()
208
-
209
- // origin/main should be at the same commit as local main (push succeeded)
210
- expect(originMainCommit).toBe(afterCommit)
211
- })
212
-
213
- test("does not push when --push flag is not set", async () => {
214
- // We're on feature branch (source)
215
- const currentBranch = await getCurrentBranch(tempDir)
216
- expect(currentBranch).toBe("agency--feature")
217
-
218
- // Get the current commit on origin/main before merge
219
- const beforeOriginCommit = (
220
- await getGitOutput(tempDir, ["rev-parse", "origin/main"])
221
- ).trim()
222
-
223
- // Run merge without push flag (skipFilter for speed, we're testing push behavior)
224
- await runTestEffect(merge({ silent: true, skipFilter: true }))
225
-
226
- // Should be on main branch after merge
227
- const afterMergeBranch = await getCurrentBranch(tempDir)
228
- expect(afterMergeBranch).toBe("main")
229
-
230
- // Get the current commit on origin/main after merge
231
- const afterOriginCommit = (
232
- await getGitOutput(tempDir, ["rev-parse", "origin/main"])
233
- ).trim()
234
-
235
- // origin/main should still be at the same commit (no push happened)
236
- expect(afterOriginCommit).toBe(beforeOriginCommit)
237
-
238
- // But local main should have moved forward
239
- const localMainCommit = (
240
- await getGitOutput(tempDir, ["rev-parse", "HEAD"])
241
- ).trim()
242
-
243
- expect(localMainCommit).not.toBe(beforeOriginCommit)
244
- })
245
- })
246
- })
@@ -1,244 +0,0 @@
1
- import { Effect } from "effect"
2
- import type { BaseCommandOptions } from "../utils/command"
3
- import { GitService, GitCommandError } from "../services/GitService"
4
- import { ConfigService } from "../services/ConfigService"
5
- import { resolveBranchPairWithAgencyJson } from "../utils/pr-branch"
6
- import { FileSystemService } from "../services/FileSystemService"
7
- import { emit } from "./emit"
8
- import highlight, { done } from "../utils/colors"
9
- import {
10
- createLoggers,
11
- ensureGitRepo,
12
- ensureBranchExists,
13
- getBaseBranchFromMetadataEffect,
14
- getBaseBranchFromBranch,
15
- getRemoteName,
16
- } from "../utils/effect"
17
-
18
- interface MergeOptions extends BaseCommandOptions {
19
- squash?: boolean
20
- push?: boolean
21
- skipFilter?: boolean
22
- }
23
-
24
- // Helper to merge a branch using git
25
- const mergeBranchEffect = (
26
- gitRoot: string,
27
- branch: string,
28
- squash: boolean = false,
29
- ) =>
30
- Effect.gen(function* () {
31
- const git = yield* GitService
32
-
33
- const result = yield* git.merge(gitRoot, branch, { squash })
34
-
35
- if (result.exitCode !== 0) {
36
- return yield* Effect.fail(
37
- new GitCommandError({
38
- command: `git merge${squash ? " --squash" : ""} ${branch}`,
39
- exitCode: result.exitCode,
40
- stderr: result.stderr,
41
- }),
42
- )
43
- }
44
- })
45
-
46
- export const merge = (options: MergeOptions = {}) =>
47
- Effect.gen(function* () {
48
- const { squash = false, push = false, verbose = false } = options
49
- const { log, verboseLog } = createLoggers(options)
50
-
51
- const git = yield* GitService
52
- const configService = yield* ConfigService
53
-
54
- const gitRoot = yield* ensureGitRepo()
55
-
56
- const config = yield* configService.loadConfig()
57
- const currentBranch = yield* git.getCurrentBranch(gitRoot)
58
-
59
- verboseLog(`Current branch: ${highlight.branch(currentBranch)}`)
60
-
61
- // Use proper branch resolution with agency.json support
62
- const fs = yield* FileSystemService
63
- const branchInfo = yield* resolveBranchPairWithAgencyJson(
64
- gitRoot,
65
- currentBranch,
66
- config.sourceBranchPattern,
67
- config.emitBranch,
68
- )
69
-
70
- let emitBranchToMerge: string
71
- let baseBranchToMergeInto: string
72
-
73
- if (branchInfo.isOnEmitBranch) {
74
- const sourceBranch = branchInfo.sourceBranch
75
- verboseLog(
76
- `Current branch appears to be an emit branch for source: ${highlight.branch(sourceBranch)}`,
77
- )
78
-
79
- yield* ensureBranchExists(
80
- gitRoot,
81
- sourceBranch,
82
- `Current branch ${highlight.branch(currentBranch)} appears to be an emit branch, but source branch ${highlight.branch(sourceBranch)} does not exist.\n` +
83
- `Cannot merge without a valid source branch.`,
84
- )
85
-
86
- // Get the base branch from the source branch's agency.json using git show
87
- // No need to checkout the branch - we can read the file directly
88
- const configuredBase = yield* getBaseBranchFromBranch(
89
- gitRoot,
90
- sourceBranch,
91
- )
92
-
93
- if (!configuredBase) {
94
- return yield* Effect.fail(
95
- new Error(
96
- `No base branch configured for ${highlight.branch(sourceBranch)}.\n` +
97
- `Please switch to ${highlight.branch(sourceBranch)} and run: agency base set <branch>`,
98
- ),
99
- )
100
- }
101
-
102
- verboseLog(`Configured base branch: ${highlight.branch(configuredBase)}`)
103
-
104
- // For git operations (checkout/merge), use local branch name
105
- baseBranchToMergeInto = git.stripRemotePrefix(configuredBase)
106
-
107
- // Verify local base branch exists
108
- yield* ensureBranchExists(
109
- gitRoot,
110
- baseBranchToMergeInto,
111
- `Base branch ${highlight.branch(baseBranchToMergeInto)} does not exist locally.\n` +
112
- `You may need to checkout the branch first or update your base branch configuration.`,
113
- )
114
-
115
- emitBranchToMerge = currentBranch
116
- } else {
117
- // We're on a source branch - need to create/update emit branch first
118
- verboseLog(
119
- `Current branch appears to be a source branch, will create emit branch first`,
120
- )
121
-
122
- // Use the emit branch from branchInfo we already computed
123
- const emitBranch = branchInfo.emitBranch
124
- const emitExists = yield* git.branchExists(gitRoot, emitBranch)
125
-
126
- if (emitExists) {
127
- verboseLog(
128
- `Emit branch ${highlight.branch(emitBranch)} already exists, will recreate it`,
129
- )
130
- }
131
-
132
- // Run 'agency emit' to create/update the emit branch
133
- verboseLog(`Creating emit branch ${highlight.branch(emitBranch)}...`)
134
- yield* emit({ silent: true, verbose, skipFilter: options.skipFilter })
135
-
136
- // emit() leaves us on the source branch, so we can read agency.json directly
137
- const configuredBase = yield* getBaseBranchFromMetadataEffect(gitRoot)
138
- if (!configuredBase) {
139
- return yield* Effect.fail(
140
- new Error(
141
- `No base branch configured for ${highlight.branch(currentBranch)}.\n` +
142
- `Please set one with: agency base set <branch>`,
143
- ),
144
- )
145
- }
146
-
147
- verboseLog(`Configured base branch: ${highlight.branch(configuredBase)}`)
148
-
149
- // For git operations (checkout/merge), use local branch name
150
- baseBranchToMergeInto = git.stripRemotePrefix(configuredBase)
151
-
152
- // Verify local base branch exists
153
- yield* ensureBranchExists(
154
- gitRoot,
155
- baseBranchToMergeInto,
156
- `Base branch ${highlight.branch(baseBranchToMergeInto)} does not exist locally.\n` +
157
- `You may need to checkout the branch first or update your base branch configuration.`,
158
- )
159
-
160
- emitBranchToMerge = emitBranch
161
- }
162
-
163
- // Now switch to the base branch
164
- verboseLog(`Switching to ${highlight.branch(baseBranchToMergeInto)}...`)
165
- yield* git.checkoutBranch(gitRoot, baseBranchToMergeInto)
166
-
167
- // Merge the emit branch
168
- verboseLog(
169
- `Merging ${highlight.branch(emitBranchToMerge)} into ${highlight.branch(baseBranchToMergeInto)}${squash ? " (squash)" : ""}...`,
170
- )
171
- yield* mergeBranchEffect(gitRoot, emitBranchToMerge, squash)
172
-
173
- if (squash) {
174
- log(done(`Squash merged (awaiting commit)`))
175
- } else {
176
- log(done("Merged"))
177
- }
178
-
179
- // Push the base branch if --push flag is set
180
- if (push) {
181
- const remote = yield* getRemoteName(gitRoot)
182
- verboseLog(
183
- `Pushing ${highlight.branch(baseBranchToMergeInto)} to ${highlight.remote(remote)}...`,
184
- )
185
-
186
- const pushResult = yield* git.push(gitRoot, remote, baseBranchToMergeInto)
187
-
188
- if (pushResult.exitCode !== 0) {
189
- return yield* Effect.fail(
190
- new GitCommandError({
191
- command: `git push ${remote} ${baseBranchToMergeInto}`,
192
- exitCode: pushResult.exitCode,
193
- stderr: pushResult.stderr,
194
- }),
195
- )
196
- }
197
-
198
- log(done(`Pushed to ${highlight.remote(remote)}`))
199
- }
200
- })
201
-
202
- export const help = `
203
- Usage: agency merge [options]
204
-
205
- Merge the current emit branch into the configured base branch.
206
-
207
- This command handles two scenarios:
208
- 1. If on an emit branch (e.g., feature--PR): Switches to the base branch and merges the emit branch
209
- 2. If on a source branch (e.g., feature): Runs 'agency emit' first to create/update the emit branch, then merges it
210
-
211
- Behavior:
212
- - Automatically detects whether you're on a source or emit branch
213
- - Retrieves the configured base branch (e.g., 'main') from git config
214
- - Switches to the base branch
215
- - Merges the emit branch into the base branch
216
- - Leaves you on the base branch after merge
217
-
218
- This is useful for local development workflows where you want to test merging
219
- your clean emit branch (without AGENTS.md modifications) into the base branch
220
- before pushing.
221
-
222
- Prerequisites:
223
- - Must be on either a source branch or its corresponding emit branch
224
- - Base branch must exist locally
225
- - For source branches: Must have a corresponding emit branch or be able to create one
226
-
227
- Options:
228
- --squash # Use squash merge instead of regular merge
229
- --push # Push the base branch to origin after merging
230
-
231
- Examples:
232
- agency merge # From source branch: creates emit branch then merges
233
- agency merge --squash # Squash merge (stages changes, requires manual commit)
234
- agency merge --push # Merge and push the base branch to origin
235
-
236
- Notes:
237
- - The command determines the base branch from git config (agency.pr.<branch>.baseBranch)
238
- - If you're on a source branch, 'agency emit' is run automatically
239
- - The emit branch must have both a source branch and base branch configured
240
- - After merge, you remain on the base branch
241
- - Merge conflicts must be resolved manually if they occur
242
- - With --squash, changes are staged but not committed (you must commit manually)
243
- - With --push, the base branch is pushed to origin after a successful merge
244
- `