@markjaquith/agency 1.11.1 → 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.
- package/README.md +302 -113
- package/cli.ts +123 -420
- package/index.ts +1 -1
- package/package.json +12 -17
- package/skills/agency/SKILL.md +258 -0
- package/src/cli.test.ts +290 -0
- package/src/commands/description.test.ts +103 -0
- package/src/commands/epic.test.ts +103 -0
- package/src/commands/epic.ts +101 -0
- package/src/commands/init.test.ts +42 -290
- package/src/commands/init.ts +15 -123
- package/src/commands/phase.ts +120 -0
- package/src/commands/pr.test.ts +19 -170
- package/src/commands/pr.ts +23 -179
- package/src/commands/repo.test.ts +80 -0
- package/src/commands/repo.ts +83 -0
- package/src/commands/status.test.ts +35 -477
- package/src/commands/status.ts +24 -213
- package/src/commands/task-phase.test.ts +206 -0
- package/src/commands/task.ts +83 -1285
- package/src/commands/validate.test.ts +91 -0
- package/src/commands/validate.ts +50 -0
- package/src/commands/work.test.ts +172 -419
- package/src/commands/work.ts +47 -166
- package/src/services/EpicService.test.ts +71 -0
- package/src/services/EpicService.ts +135 -0
- package/src/services/FileSystemService.ts +61 -92
- package/src/services/PhaseService.ts +323 -0
- package/src/services/PullRequestService.test.ts +386 -0
- package/src/services/PullRequestService.ts +143 -0
- package/src/services/RepositoryService.test.ts +106 -0
- package/src/services/RepositoryService.ts +159 -0
- package/src/services/TaskPhaseService.test.ts +217 -0
- package/src/services/TaskService.ts +192 -0
- package/src/services/WorkbaseService.test.ts +446 -0
- package/src/services/WorkbaseService.ts +493 -0
- package/src/services/WorktreeService.test.ts +599 -0
- package/src/services/WorktreeService.ts +357 -0
- package/src/test-utils.ts +41 -438
- package/src/types.ts +1 -215
- package/src/utils/command.ts +1 -5
- package/src/utils/effect.test.ts +24 -0
- package/src/utils/effect.ts +3 -273
- package/src/utils/process.test.ts +0 -15
- package/src/utils/process.ts +1 -60
- package/src/workbase/frontmatter.test.ts +50 -0
- package/src/workbase/frontmatter.ts +77 -0
- package/src/workbase/repository-reference.test.ts +25 -0
- package/src/workbase/repository-reference.ts +18 -0
- package/src/workbase/schemas.test.ts +146 -0
- package/src/workbase/schemas.ts +78 -0
- package/src/workbase/worktree-command.test.ts +61 -0
- package/src/workbase/worktree-command.ts +52 -0
- package/src/commands/base.test.ts +0 -198
- package/src/commands/base.ts +0 -198
- package/src/commands/clean.test.ts +0 -299
- package/src/commands/clean.ts +0 -274
- package/src/commands/completions.test.ts +0 -51
- package/src/commands/completions.ts +0 -308
- package/src/commands/emit.integration.test.ts +0 -549
- package/src/commands/emit.test.ts +0 -576
- package/src/commands/emit.ts +0 -700
- package/src/commands/emitted.test.ts +0 -226
- package/src/commands/emitted.ts +0 -57
- package/src/commands/loop.test.ts +0 -621
- package/src/commands/loop.ts +0 -406
- package/src/commands/merge.integration.test.ts +0 -195
- package/src/commands/merge.test.ts +0 -246
- package/src/commands/merge.ts +0 -244
- package/src/commands/pull.test.ts +0 -395
- package/src/commands/pull.ts +0 -205
- package/src/commands/push.test.ts +0 -641
- package/src/commands/push.ts +0 -482
- package/src/commands/rebase.test.ts +0 -521
- package/src/commands/rebase.ts +0 -232
- package/src/commands/save.test.ts +0 -247
- package/src/commands/save.ts +0 -162
- package/src/commands/source.test.ts +0 -195
- package/src/commands/source.ts +0 -72
- package/src/commands/switch.test.ts +0 -194
- package/src/commands/switch.ts +0 -84
- package/src/commands/task-branching.test.ts +0 -633
- package/src/commands/task-continue.test.ts +0 -311
- package/src/commands/task-edit.test.ts +0 -235
- package/src/commands/task-main.test.ts +0 -1066
- package/src/commands/task-squash.test.ts +0 -266
- package/src/commands/tasks.test.ts +0 -391
- package/src/commands/tasks.ts +0 -161
- package/src/commands/template-delete.test.ts +0 -178
- package/src/commands/template-delete.ts +0 -98
- package/src/commands/template-list.test.ts +0 -135
- package/src/commands/template-list.ts +0 -87
- package/src/commands/template-view.test.ts +0 -158
- package/src/commands/template-view.ts +0 -86
- package/src/commands/template.test.ts +0 -32
- package/src/commands/template.ts +0 -96
- package/src/commands/use.test.ts +0 -87
- package/src/commands/use.ts +0 -97
- package/src/constants.ts +0 -10
- package/src/errors.ts +0 -17
- package/src/schemas.ts +0 -33
- package/src/services/AgencyMetadataService.ts +0 -311
- package/src/services/ClaudeService.test.ts +0 -184
- package/src/services/ClaudeService.ts +0 -91
- package/src/services/ConfigService.ts +0 -115
- package/src/services/FilterRepoService.ts +0 -164
- package/src/services/FormatterService.test.ts +0 -432
- package/src/services/FormatterService.ts +0 -219
- package/src/services/GitService.ts +0 -1187
- package/src/services/MockFilterRepoService.ts +0 -140
- package/src/services/OpencodeService.ts +0 -263
- package/src/services/PromptService.ts +0 -183
- package/src/services/TemplateService.ts +0 -81
- package/src/types/native-exec.d.ts +0 -8
- package/src/utils/colors.ts +0 -178
- package/src/utils/git-path.ts +0 -6
- package/src/utils/glob.test.ts +0 -161
- package/src/utils/glob.ts +0 -78
- package/src/utils/paths.ts +0 -51
- package/src/utils/pr-branch.test.ts +0 -376
- package/src/utils/pr-branch.ts +0 -508
- package/src/utils/spinner.test.ts +0 -45
- package/src/utils/spinner.ts +0 -96
- package/src/utils/task-parser.test.ts +0 -172
- package/src/utils/task-parser.ts +0 -93
- package/templates/AGENCY.md +0 -22
- package/templates/AGENTS.md +0 -11
- package/templates/CLAUDE.md +0 -3
- package/templates/TASK.md +0 -5
- package/templates/opencode.json +0 -4
package/cli.ts
CHANGED
|
@@ -1,52 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import { parseArgs } from "util"
|
|
4
|
-
import { Effect, Layer } from "effect"
|
|
5
|
-
import { clean, help as cleanHelp } from "./src/commands/clean"
|
|
4
|
+
import { Effect, Either, Layer } from "effect"
|
|
6
5
|
import { init, help as initHelp } from "./src/commands/init"
|
|
7
|
-
import { task,
|
|
8
|
-
import { tasks, help as tasksHelp } from "./src/commands/tasks"
|
|
9
|
-
import { emit, help as emitHelp } from "./src/commands/emit"
|
|
10
|
-
import { emitted, help as emittedHelp } from "./src/commands/emitted"
|
|
6
|
+
import { task, help as taskHelp } from "./src/commands/task"
|
|
11
7
|
import { pr, help as prHelp } from "./src/commands/pr"
|
|
12
|
-
import { push, help as pushHelp } from "./src/commands/push"
|
|
13
|
-
import { pull, help as pullHelp } from "./src/commands/pull"
|
|
14
|
-
import { rebase, help as rebaseHelp } from "./src/commands/rebase"
|
|
15
|
-
import { base, help as baseHelp } from "./src/commands/base"
|
|
16
|
-
import { switchBranch, help as switchHelp } from "./src/commands/switch"
|
|
17
|
-
import { source, help as sourceHelp } from "./src/commands/source"
|
|
18
|
-
import { merge, help as mergeHelp } from "./src/commands/merge"
|
|
19
|
-
import { template, help as templateHelp } from "./src/commands/template"
|
|
20
8
|
import { work, help as workHelp } from "./src/commands/work"
|
|
21
|
-
import { loop, help as loopHelp } from "./src/commands/loop"
|
|
22
9
|
import { status, help as statusHelp } from "./src/commands/status"
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from "./src/commands/
|
|
10
|
+
import { validate, help as validateHelp } from "./src/commands/validate"
|
|
11
|
+
import { repo, help as repoHelp } from "./src/commands/repo"
|
|
12
|
+
import { epic, help as epicHelp } from "./src/commands/epic"
|
|
13
|
+
import { phase, help as phaseHelp } from "./src/commands/phase"
|
|
27
14
|
import type { Command } from "./src/types"
|
|
28
|
-
import { setColorsEnabled } from "./src/utils/colors"
|
|
29
|
-
import { GitService } from "./src/services/GitService"
|
|
30
|
-
import { ConfigService } from "./src/services/ConfigService"
|
|
31
15
|
import { FileSystemService } from "./src/services/FileSystemService"
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
16
|
+
import { WorkbaseService } from "./src/services/WorkbaseService"
|
|
17
|
+
import { RepositoryService } from "./src/services/RepositoryService"
|
|
18
|
+
import { EpicService } from "./src/services/EpicService"
|
|
19
|
+
import { TaskService } from "./src/services/TaskService"
|
|
20
|
+
import { PhaseService } from "./src/services/PhaseService"
|
|
21
|
+
import { WorktreeService } from "./src/services/WorktreeService"
|
|
22
|
+
import { PullRequestService } from "./src/services/PullRequestService"
|
|
38
23
|
|
|
39
24
|
// Create CLI layer with all services
|
|
40
25
|
const CliLayer = Layer.mergeAll(
|
|
41
|
-
GitService.Default,
|
|
42
|
-
ConfigService.Default,
|
|
43
26
|
FileSystemService.Default,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
27
|
+
WorkbaseService.Default,
|
|
28
|
+
RepositoryService.Default,
|
|
29
|
+
EpicService.Default,
|
|
30
|
+
TaskService.Default,
|
|
31
|
+
PhaseService.Default,
|
|
32
|
+
WorktreeService.Default,
|
|
33
|
+
PullRequestService.Default,
|
|
50
34
|
)
|
|
51
35
|
|
|
52
36
|
/**
|
|
@@ -61,31 +45,28 @@ async function runCommand<E>(
|
|
|
61
45
|
never
|
|
62
46
|
>
|
|
63
47
|
|
|
64
|
-
|
|
65
|
-
const programWithErrorHandling = Effect.catchAll(providedEffect, (error) => {
|
|
66
|
-
// Convert typed errors to standard Error objects with clear messages
|
|
48
|
+
const toError = (error: unknown) => {
|
|
67
49
|
if (error instanceof Error) {
|
|
68
|
-
return
|
|
50
|
+
return error
|
|
69
51
|
}
|
|
70
|
-
// Handle objects with message property (common pattern for tagged errors)
|
|
71
52
|
if (
|
|
72
53
|
typeof error === "object" &&
|
|
73
54
|
error !== null &&
|
|
74
55
|
"message" in error &&
|
|
75
56
|
typeof error.message === "string"
|
|
76
57
|
) {
|
|
77
|
-
return
|
|
58
|
+
return new Error(error.message)
|
|
78
59
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
})
|
|
60
|
+
return new Error(String(error))
|
|
61
|
+
}
|
|
82
62
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
63
|
+
const result = await Effect.runPromise(
|
|
64
|
+
providedEffect.pipe(
|
|
65
|
+
Effect.catchAllDefect((defect) => Effect.fail(toError(defect))),
|
|
66
|
+
Effect.either,
|
|
67
|
+
),
|
|
86
68
|
)
|
|
87
|
-
|
|
88
|
-
await Effect.runPromise(program)
|
|
69
|
+
if (Either.isLeft(result)) throw toError(result.left)
|
|
89
70
|
}
|
|
90
71
|
|
|
91
72
|
// Read version from package.json
|
|
@@ -97,322 +78,143 @@ const VERSION = packageJson.version
|
|
|
97
78
|
// Define commands
|
|
98
79
|
const commands: Record<string, Command> = {
|
|
99
80
|
init: {
|
|
100
|
-
|
|
101
|
-
description: "Initialize agency with template selection",
|
|
102
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
81
|
+
run: async (args: string[], options: Record<string, any>) => {
|
|
103
82
|
if (options.help) {
|
|
104
83
|
console.log(initHelp)
|
|
105
84
|
return
|
|
106
85
|
}
|
|
107
86
|
await runCommand(
|
|
108
87
|
init({
|
|
109
|
-
|
|
88
|
+
path: args[0],
|
|
89
|
+
json: options.json,
|
|
110
90
|
silent: options.silent,
|
|
111
91
|
verbose: options.verbose,
|
|
112
92
|
}),
|
|
113
93
|
)
|
|
114
94
|
},
|
|
115
|
-
help: initHelp,
|
|
116
95
|
},
|
|
117
|
-
|
|
118
|
-
name: "emit",
|
|
119
|
-
description: "Emit a branch without backpack files",
|
|
96
|
+
epic: {
|
|
120
97
|
run: async (args: string[], options: Record<string, any>) => {
|
|
121
98
|
if (options.help) {
|
|
122
|
-
console.log(
|
|
99
|
+
console.log(epicHelp)
|
|
123
100
|
return
|
|
124
101
|
}
|
|
125
102
|
await runCommand(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
103
|
+
epic({
|
|
104
|
+
subcommand: args[0],
|
|
105
|
+
args: args.slice(1),
|
|
106
|
+
ticketUrl: options["ticket-url"],
|
|
107
|
+
description: options.description,
|
|
108
|
+
repos: options.repo,
|
|
109
|
+
json: options.json,
|
|
129
110
|
silent: options.silent,
|
|
130
|
-
force: options.verbose,
|
|
131
111
|
verbose: options.verbose,
|
|
132
112
|
}),
|
|
133
113
|
)
|
|
134
114
|
},
|
|
135
|
-
help: emitHelp,
|
|
136
|
-
},
|
|
137
|
-
emitted: {
|
|
138
|
-
name: "emitted",
|
|
139
|
-
description: "Get the name of the emitted branch",
|
|
140
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
141
|
-
if (options.help) {
|
|
142
|
-
console.log(emittedHelp)
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
await runCommand(
|
|
146
|
-
emitted({ silent: options.silent, verbose: options.verbose }),
|
|
147
|
-
)
|
|
148
|
-
},
|
|
149
|
-
help: emittedHelp,
|
|
150
115
|
},
|
|
151
116
|
pr: {
|
|
152
|
-
|
|
153
|
-
description: "Run gh pr with the emitted branch name",
|
|
154
|
-
run: async (
|
|
155
|
-
_args: string[],
|
|
156
|
-
options: Record<string, any>,
|
|
157
|
-
rawArgs?: string[],
|
|
158
|
-
) => {
|
|
117
|
+
run: async (args: string[], options: Record<string, any>) => {
|
|
159
118
|
if (options.help) {
|
|
160
119
|
console.log(prHelp)
|
|
161
120
|
return
|
|
162
121
|
}
|
|
163
|
-
// Pass raw args (after filtering agency flags) directly to gh pr
|
|
164
|
-
// This allows flags like --web to pass through without needing --
|
|
165
|
-
const agencyFlags = ["--help", "-h", "--silent", "-s", "--verbose", "-v"]
|
|
166
|
-
const filteredArgs = (rawArgs ?? []).filter(
|
|
167
|
-
(arg) => !agencyFlags.includes(arg),
|
|
168
|
-
)
|
|
169
122
|
await runCommand(
|
|
170
123
|
pr({
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
},
|
|
177
|
-
help: prHelp,
|
|
178
|
-
},
|
|
179
|
-
push: {
|
|
180
|
-
name: "push",
|
|
181
|
-
description: "Push the emitted branch or fall through to git push",
|
|
182
|
-
run: async (args: string[], options: Record<string, any>) => {
|
|
183
|
-
if (options.help) {
|
|
184
|
-
console.log(pushHelp)
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
await runCommand(
|
|
188
|
-
push({
|
|
189
|
-
baseBranch: args[0],
|
|
190
|
-
gitArgs: args,
|
|
191
|
-
emit: options.emit || options.branch,
|
|
192
|
-
silent: options.silent,
|
|
193
|
-
force: options.force,
|
|
194
|
-
forceWithLease: options["force-with-lease"],
|
|
195
|
-
noVerify: options["no-verify"],
|
|
196
|
-
verbose: options.verbose,
|
|
197
|
-
pr: options.pr,
|
|
198
|
-
}),
|
|
199
|
-
)
|
|
200
|
-
},
|
|
201
|
-
help: pushHelp,
|
|
202
|
-
},
|
|
203
|
-
pull: {
|
|
204
|
-
name: "pull",
|
|
205
|
-
description: "Pull commits from remote emit branch to source",
|
|
206
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
207
|
-
if (options.help) {
|
|
208
|
-
console.log(pullHelp)
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
await runCommand(
|
|
212
|
-
pull({
|
|
213
|
-
remote: options.remote,
|
|
214
|
-
silent: options.silent,
|
|
215
|
-
verbose: options.verbose,
|
|
216
|
-
}),
|
|
217
|
-
)
|
|
218
|
-
},
|
|
219
|
-
help: pullHelp,
|
|
220
|
-
},
|
|
221
|
-
rebase: {
|
|
222
|
-
name: "rebase",
|
|
223
|
-
description: "Rebase source branch onto base branch",
|
|
224
|
-
run: async (args: string[], options: Record<string, any>) => {
|
|
225
|
-
if (options.help) {
|
|
226
|
-
console.log(rebaseHelp)
|
|
227
|
-
return
|
|
228
|
-
}
|
|
229
|
-
await runCommand(
|
|
230
|
-
rebase({
|
|
231
|
-
baseBranch: args[0],
|
|
232
|
-
emit: options.emit || options.branch,
|
|
124
|
+
subcommand: args[0],
|
|
125
|
+
taskId: args[1],
|
|
126
|
+
phaseId: args[2],
|
|
127
|
+
draft: options.draft,
|
|
128
|
+
json: options.json,
|
|
233
129
|
silent: options.silent,
|
|
234
130
|
verbose: options.verbose,
|
|
235
131
|
}),
|
|
236
132
|
)
|
|
237
133
|
},
|
|
238
|
-
help: rebaseHelp,
|
|
239
134
|
},
|
|
240
|
-
|
|
241
|
-
name: "template",
|
|
242
|
-
description: "Template management commands",
|
|
135
|
+
phase: {
|
|
243
136
|
run: async (args: string[], options: Record<string, any>) => {
|
|
244
|
-
if (options.help)
|
|
245
|
-
console.log(templateHelp)
|
|
246
|
-
return
|
|
247
|
-
}
|
|
137
|
+
if (options.help) return console.log(phaseHelp)
|
|
248
138
|
await runCommand(
|
|
249
|
-
|
|
139
|
+
phase({
|
|
250
140
|
subcommand: args[0],
|
|
251
141
|
args: args.slice(1),
|
|
142
|
+
description: options.description,
|
|
143
|
+
repo: options.repo?.[0],
|
|
144
|
+
references: options.reference,
|
|
145
|
+
branch: options.branch,
|
|
146
|
+
base: options.base,
|
|
147
|
+
dependsOn: options["depends-on"],
|
|
148
|
+
firstPhase: options["first-phase"],
|
|
149
|
+
json: options.json,
|
|
252
150
|
silent: options.silent,
|
|
253
151
|
verbose: options.verbose,
|
|
254
|
-
template: options.template,
|
|
255
152
|
}),
|
|
256
153
|
)
|
|
257
154
|
},
|
|
258
|
-
help: templateHelp,
|
|
259
155
|
},
|
|
260
|
-
|
|
261
|
-
name: "base",
|
|
262
|
-
description: "Get or set the base branch",
|
|
156
|
+
repo: {
|
|
263
157
|
run: async (args: string[], options: Record<string, any>) => {
|
|
264
158
|
if (options.help) {
|
|
265
|
-
console.log(
|
|
159
|
+
console.log(repoHelp)
|
|
266
160
|
return
|
|
267
161
|
}
|
|
268
162
|
await runCommand(
|
|
269
|
-
|
|
163
|
+
repo({
|
|
270
164
|
subcommand: args[0],
|
|
271
165
|
args: args.slice(1),
|
|
272
|
-
repo: options.repo,
|
|
273
|
-
silent: options.silent,
|
|
274
|
-
verbose: options.verbose,
|
|
275
|
-
}),
|
|
276
|
-
)
|
|
277
|
-
},
|
|
278
|
-
help: baseHelp,
|
|
279
|
-
},
|
|
280
|
-
switch: {
|
|
281
|
-
name: "switch",
|
|
282
|
-
description: "Toggle between source and emitted branch",
|
|
283
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
284
|
-
if (options.help) {
|
|
285
|
-
console.log(switchHelp)
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
await runCommand(
|
|
289
|
-
switchBranch({ silent: options.silent, verbose: options.verbose }),
|
|
290
|
-
)
|
|
291
|
-
},
|
|
292
|
-
help: switchHelp,
|
|
293
|
-
},
|
|
294
|
-
source: {
|
|
295
|
-
name: "source",
|
|
296
|
-
description: "Switch to source branch from emitted branch",
|
|
297
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
298
|
-
if (options.help) {
|
|
299
|
-
console.log(sourceHelp)
|
|
300
|
-
return
|
|
301
|
-
}
|
|
302
|
-
await runCommand(
|
|
303
|
-
source({ silent: options.silent, verbose: options.verbose }),
|
|
304
|
-
)
|
|
305
|
-
},
|
|
306
|
-
help: sourceHelp,
|
|
307
|
-
},
|
|
308
|
-
merge: {
|
|
309
|
-
name: "merge",
|
|
310
|
-
description: "Merge emitted branch into base branch",
|
|
311
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
312
|
-
if (options.help) {
|
|
313
|
-
console.log(mergeHelp)
|
|
314
|
-
return
|
|
315
|
-
}
|
|
316
|
-
await runCommand(
|
|
317
|
-
merge({
|
|
318
166
|
silent: options.silent,
|
|
319
167
|
verbose: options.verbose,
|
|
320
|
-
|
|
321
|
-
push: options.push,
|
|
168
|
+
json: options.json,
|
|
322
169
|
}),
|
|
323
170
|
)
|
|
324
171
|
},
|
|
325
|
-
help: mergeHelp,
|
|
326
172
|
},
|
|
327
173
|
task: {
|
|
328
|
-
name: "task",
|
|
329
|
-
description: "Task management commands",
|
|
330
174
|
run: async (args: string[], options: Record<string, any>) => {
|
|
331
175
|
if (options.help) {
|
|
332
176
|
console.log(taskHelp)
|
|
333
177
|
return
|
|
334
178
|
}
|
|
335
|
-
// Initialize with optional branch name
|
|
336
|
-
const branch = args[0] || options.emit || options.branch
|
|
337
179
|
await runCommand(
|
|
338
180
|
task({
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
},
|
|
350
|
-
help: taskHelp,
|
|
351
|
-
},
|
|
352
|
-
tasks: {
|
|
353
|
-
name: "tasks",
|
|
354
|
-
description: "List all task branches",
|
|
355
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
356
|
-
if (options.help) {
|
|
357
|
-
console.log(tasksHelp)
|
|
358
|
-
return
|
|
359
|
-
}
|
|
360
|
-
await runCommand(
|
|
361
|
-
tasks({
|
|
362
|
-
silent: options.silent,
|
|
363
|
-
verbose: options.verbose,
|
|
181
|
+
subcommand: args[0],
|
|
182
|
+
args: args.slice(1),
|
|
183
|
+
ticketUrl: options["ticket-url"],
|
|
184
|
+
description: options.description,
|
|
185
|
+
epic: options.epic,
|
|
186
|
+
repo: options.repo?.[0],
|
|
187
|
+
references: options.reference,
|
|
188
|
+
branch: options.branch,
|
|
189
|
+
base: options.base,
|
|
190
|
+
multiPhase: options["multi-phase"],
|
|
364
191
|
json: options.json,
|
|
365
|
-
}),
|
|
366
|
-
)
|
|
367
|
-
},
|
|
368
|
-
help: tasksHelp,
|
|
369
|
-
},
|
|
370
|
-
edit: {
|
|
371
|
-
name: "edit",
|
|
372
|
-
description: "Open TASK.md in system editor",
|
|
373
|
-
run: async (_args: string[], options: Record<string, any>) => {
|
|
374
|
-
if (options.help) {
|
|
375
|
-
console.log(editHelp)
|
|
376
|
-
return
|
|
377
|
-
}
|
|
378
|
-
await runCommand(
|
|
379
|
-
taskEdit({
|
|
380
192
|
silent: options.silent,
|
|
381
193
|
verbose: options.verbose,
|
|
382
194
|
}),
|
|
383
195
|
)
|
|
384
196
|
},
|
|
385
|
-
help: editHelp,
|
|
386
197
|
},
|
|
387
198
|
work: {
|
|
388
|
-
name: "work",
|
|
389
|
-
description: "Start working on TASK.md with OpenCode",
|
|
390
199
|
run: async (args: string[], options: Record<string, any>) => {
|
|
391
200
|
if (options.help) {
|
|
392
201
|
console.log(workHelp)
|
|
393
202
|
return
|
|
394
203
|
}
|
|
395
204
|
|
|
396
|
-
// Extract extra args (anything after --)
|
|
397
|
-
// Note: parseArgs with strict:false and allowPositionals:true will put
|
|
398
|
-
// args after -- in the positionals array
|
|
399
|
-
const extraArgs = args.length > 0 ? args : undefined
|
|
400
|
-
|
|
401
205
|
await runCommand(
|
|
402
206
|
work({
|
|
207
|
+
taskId: args[0],
|
|
208
|
+
phaseId: args[1],
|
|
403
209
|
silent: options.silent,
|
|
404
210
|
verbose: options.verbose,
|
|
405
211
|
opencode: options.opencode,
|
|
406
212
|
claude: options.claude,
|
|
407
|
-
extraArgs,
|
|
408
213
|
}),
|
|
409
214
|
)
|
|
410
215
|
},
|
|
411
|
-
help: workHelp,
|
|
412
216
|
},
|
|
413
217
|
status: {
|
|
414
|
-
name: "status",
|
|
415
|
-
description: "Show agency status for this repository",
|
|
416
218
|
run: async (_args: string[], options: Record<string, any>) => {
|
|
417
219
|
if (options.help) {
|
|
418
220
|
console.log(statusHelp)
|
|
@@ -426,66 +228,21 @@ const commands: Record<string, Command> = {
|
|
|
426
228
|
}),
|
|
427
229
|
)
|
|
428
230
|
},
|
|
429
|
-
help: statusHelp,
|
|
430
231
|
},
|
|
431
|
-
|
|
432
|
-
name: "clean",
|
|
433
|
-
description: "Delete branches merged into a specified branch",
|
|
232
|
+
validate: {
|
|
434
233
|
run: async (_args: string[], options: Record<string, any>) => {
|
|
435
234
|
if (options.help) {
|
|
436
|
-
console.log(
|
|
235
|
+
console.log(validateHelp)
|
|
437
236
|
return
|
|
438
237
|
}
|
|
439
238
|
await runCommand(
|
|
440
|
-
|
|
239
|
+
validate({
|
|
441
240
|
silent: options.silent,
|
|
442
241
|
verbose: options.verbose,
|
|
443
|
-
|
|
444
|
-
mergedInto: options["merged-into"],
|
|
445
|
-
}),
|
|
446
|
-
)
|
|
447
|
-
},
|
|
448
|
-
help: cleanHelp,
|
|
449
|
-
},
|
|
450
|
-
loop: {
|
|
451
|
-
name: "loop",
|
|
452
|
-
description: "Run a Ralph Wiggum loop to complete all tasks",
|
|
453
|
-
run: async (args: string[], options: Record<string, any>) => {
|
|
454
|
-
if (options.help) {
|
|
455
|
-
console.log(loopHelp)
|
|
456
|
-
return
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Extract extra args (anything after --)
|
|
460
|
-
// Note: parseArgs with strict:false and allowPositionals:true will put
|
|
461
|
-
// args after -- in the positionals array
|
|
462
|
-
const extraArgs = args.length > 0 ? args : undefined
|
|
463
|
-
|
|
464
|
-
await runCommand(
|
|
465
|
-
loop({
|
|
466
|
-
silent: options.silent,
|
|
467
|
-
verbose: options.verbose,
|
|
468
|
-
maxLoops: options["max-loops"],
|
|
469
|
-
minLoops: options["min-loops"],
|
|
470
|
-
opencode: options.opencode,
|
|
471
|
-
claude: options.claude,
|
|
472
|
-
extraArgs,
|
|
242
|
+
json: options.json,
|
|
473
243
|
}),
|
|
474
244
|
)
|
|
475
245
|
},
|
|
476
|
-
help: loopHelp,
|
|
477
|
-
},
|
|
478
|
-
completions: {
|
|
479
|
-
name: "completions",
|
|
480
|
-
description: "Generate shell completion scripts",
|
|
481
|
-
run: async (args: string[], options: Record<string, any>) => {
|
|
482
|
-
if (options.help) {
|
|
483
|
-
console.log(completionsHelp)
|
|
484
|
-
return
|
|
485
|
-
}
|
|
486
|
-
await runCommand(completions(args[0]))
|
|
487
|
-
},
|
|
488
|
-
help: completionsHelp,
|
|
489
246
|
},
|
|
490
247
|
}
|
|
491
248
|
|
|
@@ -496,55 +253,36 @@ agency v${VERSION}
|
|
|
496
253
|
Usage: agency <command> [options]
|
|
497
254
|
|
|
498
255
|
Commands:
|
|
499
|
-
init
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
work
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
view <file> View contents of a file in template
|
|
509
|
-
delete <file> ... Delete files from configured template
|
|
510
|
-
emit [base-branch] Emit a branch with backpack files reverted
|
|
511
|
-
emitted Get the name of the emitted branch
|
|
512
|
-
pr <subcommand> Run gh pr with the emitted branch name
|
|
513
|
-
push [arguments] Push the emitted branch or fall through to git push
|
|
514
|
-
pull Pull commits from remote emit branch to source
|
|
515
|
-
rebase [base-branch] Rebase source branch onto base branch
|
|
516
|
-
base Get or set the base branch
|
|
517
|
-
set <branch> Set the base branch for the current feature branch
|
|
518
|
-
get Get the configured base branch
|
|
519
|
-
switch Toggle between source and emitted branch
|
|
520
|
-
source Switch to source branch from emitted branch
|
|
521
|
-
merge Merge emitted branch into base branch
|
|
522
|
-
status Show agency status for this repository
|
|
523
|
-
completions <shell> Generate bash or zsh completion scripts
|
|
256
|
+
init [path] Initialize an Agency workbase
|
|
257
|
+
epic <subcommand> Manage epics
|
|
258
|
+
phase <subcommand> Manage task phases
|
|
259
|
+
task <subcommand> Manage tasks
|
|
260
|
+
work <task> [phase] Materialize worktrees and launch an agent
|
|
261
|
+
pr create Create a pull request for an execution unit
|
|
262
|
+
repo <subcommand> Manage workbase repositories
|
|
263
|
+
status Show status for the current workbase
|
|
264
|
+
validate Validate the current workbase
|
|
524
265
|
|
|
525
266
|
Global Options:
|
|
526
267
|
-h, --help Show help for a command
|
|
527
|
-
-
|
|
528
|
-
--no-color Disable color output
|
|
268
|
+
-V, --version Show version number
|
|
529
269
|
-s, --silent Suppress output messages
|
|
530
270
|
-v, --verbose Show verbose output including detailed debugging info
|
|
531
271
|
|
|
532
272
|
Examples:
|
|
533
|
-
agency init # Initialize
|
|
534
|
-
agency task
|
|
535
|
-
agency
|
|
536
|
-
agency emit # Emit a branch (prompts for base branch)
|
|
537
|
-
agency switch # Toggle between source and emitted branch
|
|
273
|
+
agency init # Initialize the current directory
|
|
274
|
+
agency task list # List tasks
|
|
275
|
+
agency work refresh-cli-copy # Start working on a task
|
|
538
276
|
|
|
539
277
|
For more information about a command, run:
|
|
540
278
|
agency <command> --help
|
|
541
279
|
`)
|
|
542
280
|
}
|
|
543
281
|
|
|
544
|
-
// Parse global arguments
|
|
545
282
|
try {
|
|
283
|
+
const args = process.argv.slice(2)
|
|
546
284
|
const { values, positionals } = parseArgs({
|
|
547
|
-
args
|
|
285
|
+
args,
|
|
548
286
|
options: {
|
|
549
287
|
help: {
|
|
550
288
|
type: "boolean",
|
|
@@ -552,21 +290,21 @@ try {
|
|
|
552
290
|
},
|
|
553
291
|
version: {
|
|
554
292
|
type: "boolean",
|
|
555
|
-
short: "
|
|
293
|
+
short: "V",
|
|
556
294
|
},
|
|
557
|
-
|
|
295
|
+
silent: {
|
|
558
296
|
type: "boolean",
|
|
297
|
+
short: "s",
|
|
298
|
+
},
|
|
299
|
+
verbose: {
|
|
300
|
+
type: "boolean",
|
|
301
|
+
short: "v",
|
|
559
302
|
},
|
|
560
303
|
},
|
|
561
304
|
strict: false,
|
|
562
305
|
allowPositionals: true,
|
|
563
306
|
})
|
|
564
307
|
|
|
565
|
-
// Handle --no-color flag
|
|
566
|
-
if (values["no-color"]) {
|
|
567
|
-
setColorsEnabled(false)
|
|
568
|
-
}
|
|
569
|
-
|
|
570
308
|
// Handle global flags
|
|
571
309
|
if (values.version) {
|
|
572
310
|
console.log(`v${VERSION}`)
|
|
@@ -579,13 +317,7 @@ try {
|
|
|
579
317
|
// Show help if no command
|
|
580
318
|
if (!commandName) {
|
|
581
319
|
showMainHelp()
|
|
582
|
-
process.exit(1)
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// Show main help if --help with no command
|
|
586
|
-
if (values.help && !commandName) {
|
|
587
|
-
showMainHelp()
|
|
588
|
-
process.exit(0)
|
|
320
|
+
process.exit(values.help ? 0 : 1)
|
|
589
321
|
}
|
|
590
322
|
|
|
591
323
|
// Check if command exists
|
|
@@ -596,8 +328,11 @@ try {
|
|
|
596
328
|
process.exit(1)
|
|
597
329
|
}
|
|
598
330
|
|
|
599
|
-
|
|
600
|
-
const commandArgs =
|
|
331
|
+
const commandIndex = args.indexOf(commandName)
|
|
332
|
+
const commandArgs = [
|
|
333
|
+
...args.slice(0, commandIndex),
|
|
334
|
+
...args.slice(commandIndex + 1),
|
|
335
|
+
]
|
|
601
336
|
const { values: cmdValues, positionals: cmdPositionals } = parseArgs({
|
|
602
337
|
args: commandArgs,
|
|
603
338
|
options: {
|
|
@@ -609,67 +344,36 @@ try {
|
|
|
609
344
|
type: "boolean",
|
|
610
345
|
short: "s",
|
|
611
346
|
},
|
|
612
|
-
force: {
|
|
613
|
-
type: "boolean",
|
|
614
|
-
short: "f",
|
|
615
|
-
},
|
|
616
|
-
"force-with-lease": {
|
|
617
|
-
type: "boolean",
|
|
618
|
-
},
|
|
619
|
-
"no-verify": {
|
|
620
|
-
type: "boolean",
|
|
621
|
-
},
|
|
622
347
|
verbose: {
|
|
623
348
|
type: "boolean",
|
|
624
349
|
short: "v",
|
|
625
350
|
},
|
|
626
|
-
template: {
|
|
627
|
-
type: "string",
|
|
628
|
-
short: "t",
|
|
629
|
-
},
|
|
630
|
-
emit: {
|
|
631
|
-
type: "string",
|
|
632
|
-
},
|
|
633
351
|
branch: {
|
|
634
352
|
type: "string",
|
|
635
353
|
},
|
|
636
|
-
task: {
|
|
637
|
-
type: "string",
|
|
638
|
-
},
|
|
639
|
-
from: {
|
|
640
|
-
type: "string",
|
|
641
|
-
},
|
|
642
|
-
"from-current": {
|
|
643
|
-
type: "boolean",
|
|
644
|
-
},
|
|
645
|
-
continue: {
|
|
646
|
-
type: "boolean",
|
|
647
|
-
},
|
|
648
354
|
json: {
|
|
649
355
|
type: "boolean",
|
|
650
356
|
},
|
|
651
|
-
|
|
652
|
-
type: "
|
|
653
|
-
},
|
|
654
|
-
pr: {
|
|
655
|
-
type: "boolean",
|
|
656
|
-
},
|
|
657
|
-
squash: {
|
|
658
|
-
type: "boolean",
|
|
659
|
-
},
|
|
660
|
-
push: {
|
|
661
|
-
type: "boolean",
|
|
357
|
+
"ticket-url": {
|
|
358
|
+
type: "string",
|
|
662
359
|
},
|
|
663
|
-
|
|
360
|
+
description: {
|
|
664
361
|
type: "string",
|
|
665
|
-
short: "r",
|
|
666
362
|
},
|
|
667
|
-
|
|
363
|
+
repo: {
|
|
668
364
|
type: "string",
|
|
365
|
+
multiple: true,
|
|
669
366
|
},
|
|
670
|
-
|
|
671
|
-
type: "
|
|
367
|
+
reference: {
|
|
368
|
+
type: "string",
|
|
369
|
+
multiple: true,
|
|
672
370
|
},
|
|
371
|
+
epic: { type: "string" },
|
|
372
|
+
base: { type: "string" },
|
|
373
|
+
"multi-phase": { type: "boolean" },
|
|
374
|
+
"depends-on": { type: "string", multiple: true },
|
|
375
|
+
"first-phase": { type: "string" },
|
|
376
|
+
draft: { type: "boolean" },
|
|
673
377
|
opencode: {
|
|
674
378
|
type: "boolean",
|
|
675
379
|
},
|
|
@@ -681,8 +385,7 @@ try {
|
|
|
681
385
|
allowPositionals: true,
|
|
682
386
|
})
|
|
683
387
|
|
|
684
|
-
|
|
685
|
-
await command.run(cmdPositionals, cmdValues, commandArgs)
|
|
388
|
+
await command.run(cmdPositionals, cmdValues)
|
|
686
389
|
} catch (error) {
|
|
687
390
|
if (error instanceof Error) {
|
|
688
391
|
let message = error.message
|