@markjaquith/agency 2.7.1 → 2.7.3
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 +10 -1
- package/cli.ts +10 -98
- package/package.json +1 -1
- package/skills/agency/SKILL.md +6 -1
- package/src/cli-parser.test.ts +203 -0
- package/src/cli-parser.ts +555 -0
- package/src/cli.test.ts +26 -2
- package/src/commands/task.test.ts +43 -0
- package/src/commands/task.ts +75 -38
- package/src/commands/validate.test.ts +28 -0
- package/src/commands/validate.ts +10 -1
- package/src/commands/work.test.ts +96 -17
- package/src/commands/work.ts +16 -3
- package/src/services/PullRequestService.test.ts +14 -0
- package/src/services/WorktreeService.test.ts +85 -9
- package/src/services/WorktreeService.ts +39 -24
- package/src/utils/command.ts +2 -0
- package/src/workbase/workbase-choice.ts +8 -0
|
@@ -60,6 +60,11 @@ const formatCommand = (args: readonly string[]) =>
|
|
|
60
60
|
)
|
|
61
61
|
.join(" ")
|
|
62
62
|
|
|
63
|
+
const isCommitId = (ref: string) => /^[0-9a-f]{40,64}$/i.test(ref)
|
|
64
|
+
|
|
65
|
+
const originRef = (ref: string) =>
|
|
66
|
+
ref.replace(/^refs\/remotes\/origin\//, "").replace(/^origin\//, "")
|
|
67
|
+
|
|
63
68
|
export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
64
69
|
"WorktreeService",
|
|
65
70
|
{
|
|
@@ -80,12 +85,10 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
80
85
|
options.verbose === true && !options.silent && !options.json
|
|
81
86
|
const { root, config } = yield* workbase.loadConfig(startPath)
|
|
82
87
|
const report = yield* workbase.validate(root)
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
if (ownershipIssue) {
|
|
88
|
+
const validationIssue = report.issues[0]
|
|
89
|
+
if (validationIssue) {
|
|
87
90
|
return yield* new WorktreeError({
|
|
88
|
-
message: `${
|
|
91
|
+
message: `${validationIssue.path}: ${validationIssue.message}`,
|
|
89
92
|
})
|
|
90
93
|
}
|
|
91
94
|
const task = yield* tasks.show(taskId, root)
|
|
@@ -136,23 +139,32 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
136
139
|
})
|
|
137
140
|
}
|
|
138
141
|
|
|
139
|
-
const fetchOrigin =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
const fetchOrigin = (ref?: string) =>
|
|
143
|
+
Effect.gen(function* () {
|
|
144
|
+
const remote = yield* fs.runCommand(
|
|
145
|
+
["git", "-C", repositoryPath, "remote", "get-url", "origin"],
|
|
146
|
+
{ captureOutput: true },
|
|
147
|
+
)
|
|
148
|
+
if (remote.exitCode !== 0) return false
|
|
145
149
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
const fetch = yield* fs.runCommand(
|
|
151
|
+
[
|
|
152
|
+
"git",
|
|
153
|
+
"-C",
|
|
154
|
+
repositoryPath,
|
|
155
|
+
"fetch",
|
|
156
|
+
"origin",
|
|
157
|
+
...(ref ? [ref] : []),
|
|
158
|
+
],
|
|
159
|
+
{ captureOutput: true },
|
|
160
|
+
)
|
|
161
|
+
if (fetch.exitCode !== 0) {
|
|
162
|
+
return yield* new WorktreeError({
|
|
163
|
+
message: `Failed to fetch '${alias}': ${fetch.stderr}`,
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
return true
|
|
167
|
+
})
|
|
156
168
|
|
|
157
169
|
const listed = yield* fs.runCommand(
|
|
158
170
|
[
|
|
@@ -210,7 +222,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
210
222
|
message: `Worktree registry contains a missing checkout at ${checkoutPath}`,
|
|
211
223
|
})
|
|
212
224
|
}
|
|
213
|
-
yield* fetchOrigin
|
|
225
|
+
yield* fetchOrigin()
|
|
214
226
|
|
|
215
227
|
let args: string[]
|
|
216
228
|
let env: Record<string, string> | undefined
|
|
@@ -297,6 +309,10 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
297
309
|
})
|
|
298
310
|
}
|
|
299
311
|
} else {
|
|
312
|
+
const fetched = isCommitId(checkout.ref)
|
|
313
|
+
? false
|
|
314
|
+
: yield* fetchOrigin(originRef(checkout.ref))
|
|
315
|
+
const resolvedRefName = fetched ? "FETCH_HEAD" : checkout.ref
|
|
300
316
|
const resolvedRef = yield* fs.runCommand(
|
|
301
317
|
[
|
|
302
318
|
"git",
|
|
@@ -304,7 +320,7 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
304
320
|
repositoryPath,
|
|
305
321
|
"rev-parse",
|
|
306
322
|
"--verify",
|
|
307
|
-
`${
|
|
323
|
+
`${resolvedRefName}^{commit}`,
|
|
308
324
|
],
|
|
309
325
|
{ captureOutput: true },
|
|
310
326
|
)
|
|
@@ -344,7 +360,6 @@ export class WorktreeService extends Effect.Service<WorktreeService>()(
|
|
|
344
360
|
message: `Worktree registry contains a missing checkout at ${checkoutPath}`,
|
|
345
361
|
})
|
|
346
362
|
}
|
|
347
|
-
yield* fetchOrigin
|
|
348
363
|
const result = yield* fs.runCommand(
|
|
349
364
|
[
|
|
350
365
|
"git",
|
package/src/utils/command.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface BaseCommandOptions {
|
|
|
5
5
|
readonly silent?: boolean
|
|
6
6
|
readonly verbose?: boolean
|
|
7
7
|
readonly json?: boolean
|
|
8
|
+
/** Whether this invocation may open prompts or selectors. */
|
|
9
|
+
readonly inputAllowed?: boolean
|
|
8
10
|
/**
|
|
9
11
|
* Working directory to use instead of process.cwd().
|
|
10
12
|
* Primarily used for testing to enable concurrent test execution.
|
|
@@ -34,6 +34,7 @@ export const resolveWorkbase = (
|
|
|
34
34
|
startPath: string,
|
|
35
35
|
log: (message: string) => void,
|
|
36
36
|
pick: PickWorkbase = pickWorkbase,
|
|
37
|
+
inputAllowed = true,
|
|
37
38
|
) =>
|
|
38
39
|
Effect.gen(function* () {
|
|
39
40
|
const fs = yield* FileSystemService
|
|
@@ -50,6 +51,13 @@ export const resolveWorkbase = (
|
|
|
50
51
|
),
|
|
51
52
|
)
|
|
52
53
|
}
|
|
54
|
+
if (!inputAllowed) {
|
|
55
|
+
return yield* Effect.fail(
|
|
56
|
+
new Error(
|
|
57
|
+
"Workbase selection requires interactive input; provide an explicit path or run Agency from a workbase",
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
}
|
|
53
61
|
|
|
54
62
|
const fzf = yield* fs.runCommand(["which", "fzf"], {
|
|
55
63
|
captureOutput: true,
|