@markjaquith/agency 3.2.13 → 3.2.15
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/package.json +7 -2
- package/src/workbase/schemas.ts +12 -0
- package/fixtures/protocol/orchestration-recipes.json +0 -53
- package/pi-extensions/agency.test.ts +0 -117
- package/src/check-commits.test.ts +0 -58
- package/src/cli-parser.test.ts +0 -945
- package/src/cli.test.ts +0 -1889
- package/src/commands/act.test.ts +0 -418
- package/src/commands/archive.test.ts +0 -236
- package/src/commands/context.test.ts +0 -665
- package/src/commands/description.test.ts +0 -103
- package/src/commands/doctor.test.ts +0 -185
- package/src/commands/epic.test.ts +0 -196
- package/src/commands/init.test.ts +0 -117
- package/src/commands/integration.test.ts +0 -165
- package/src/commands/pr.test.ts +0 -248
- package/src/commands/push.test.ts +0 -56
- package/src/commands/read-only.test.ts +0 -161
- package/src/commands/repo.test.ts +0 -199
- package/src/commands/restore.test.ts +0 -106
- package/src/commands/status.test.ts +0 -113
- package/src/commands/sync.test.ts +0 -200
- package/src/commands/task-phase.test.ts +0 -410
- package/src/commands/task.test.ts +0 -281
- package/src/commands/validate.test.ts +0 -186
- package/src/commands/work.test.ts +0 -1375
- package/src/commands/workbase.test.ts +0 -170
- package/src/graph-schema.test.ts +0 -124
- package/src/protocol.test.ts +0 -163
- package/src/readiness.test.ts +0 -105
- package/src/services/ArchiveBulkService.test.ts +0 -384
- package/src/services/ArchiveService.test.ts +0 -1092
- package/src/services/EpicService.test.ts +0 -74
- package/src/services/FileSystemService.test.ts +0 -81
- package/src/services/GraphMutationService.test.ts +0 -486
- package/src/services/GraphService.test.ts +0 -494
- package/src/services/IntegrationService.test.ts +0 -1091
- package/src/services/LifecycleTransaction.test.ts +0 -145
- package/src/services/PullRequestService.test.ts +0 -716
- package/src/services/PushService.test.ts +0 -408
- package/src/services/ReadinessService.test.ts +0 -290
- package/src/services/RepositoryService.test.ts +0 -789
- package/src/services/ReviewService.test.ts +0 -408
- package/src/services/SyncService.test.ts +0 -1377
- package/src/services/TaskPhaseService.test.ts +0 -852
- package/src/services/VersionControlService.test.ts +0 -62
- package/src/services/WorkbaseService.test.ts +0 -910
- package/src/services/WorktreeLock.test.ts +0 -205
- package/src/services/WorktreePerformance.test.ts +0 -71
- package/src/services/WorktreeService.test.ts +0 -2292
- package/src/test-utils.ts +0 -110
- package/src/usage-log.test.ts +0 -188
- package/src/utils/chooser.test.ts +0 -192
- package/src/utils/effect.test.ts +0 -30
- package/src/utils/interactive.pty.test.ts +0 -128
- package/src/utils/interactive.test.tsx +0 -860
- package/src/utils/process.test.ts +0 -132
- package/src/utils/progress.test.ts +0 -37
- package/src/work-view.test.ts +0 -151
- package/src/workbase/agent-command.test.ts +0 -128
- package/src/workbase/checkout-command.test.ts +0 -62
- package/src/workbase/delivery-command.test.ts +0 -180
- package/src/workbase/dependency-graph.test.ts +0 -50
- package/src/workbase/execution-contract.test.ts +0 -161
- package/src/workbase/frontmatter.test.ts +0 -67
- package/src/workbase/repository-reference.test.ts +0 -25
- package/src/workbase/schemas.test.ts +0 -543
- package/src/workbase/work-target.test.ts +0 -108
- package/src/workbase/worktree-command.test.ts +0 -61
package/src/cli-parser.test.ts
DELETED
|
@@ -1,945 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test"
|
|
2
|
-
import orchestrationRecipes from "../fixtures/protocol/orchestration-recipes.json"
|
|
3
|
-
import { parseCli } from "./cli-parser"
|
|
4
|
-
|
|
5
|
-
const expectUsageError = (args: string[], usage: string) => {
|
|
6
|
-
expect(() => parseCli(args)).toThrow(`Usage: ${usage}`)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
describe("strict CLI parsing", () => {
|
|
10
|
-
test("returns canonical paths without positional values", () => {
|
|
11
|
-
expect(parseCli(["task", "show", "private-task-id"]).commandPath).toBe(
|
|
12
|
-
"task/show",
|
|
13
|
-
)
|
|
14
|
-
expect(parseCli(["validate", "/private/customer/path"]).commandPath).toBe(
|
|
15
|
-
"validate",
|
|
16
|
-
)
|
|
17
|
-
expect(parseCli(["work", "prepare", "private-task-id"]).commandPath).toBe(
|
|
18
|
-
"work/prepare",
|
|
19
|
-
)
|
|
20
|
-
expect(parseCli(["pr", "view", "private-task-id"]).commandPath).toBe("pr")
|
|
21
|
-
try {
|
|
22
|
-
parseCli(["task", "create", "private-task-id"])
|
|
23
|
-
expect.unreachable()
|
|
24
|
-
} catch (error) {
|
|
25
|
-
expect(error).toMatchObject({ commandPath: "task/create" })
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test("parses act selectors, dry-run, and JSON options", () => {
|
|
30
|
-
expect(
|
|
31
|
-
parseCli([
|
|
32
|
-
"act",
|
|
33
|
-
"--task",
|
|
34
|
-
"example",
|
|
35
|
-
"--phase",
|
|
36
|
-
"build",
|
|
37
|
-
"--dry-run",
|
|
38
|
-
"--auto",
|
|
39
|
-
"--draft",
|
|
40
|
-
]),
|
|
41
|
-
).toMatchObject({
|
|
42
|
-
commandName: "act",
|
|
43
|
-
args: [],
|
|
44
|
-
values: {
|
|
45
|
-
task: "example",
|
|
46
|
-
phase: "build",
|
|
47
|
-
"dry-run": true,
|
|
48
|
-
auto: true,
|
|
49
|
-
draft: true,
|
|
50
|
-
},
|
|
51
|
-
})
|
|
52
|
-
expect(parseCli(["act", "--json"]).values.json).toBe(true)
|
|
53
|
-
expect(parseCli(["act", "task-id"]).args).toEqual(["task-id"])
|
|
54
|
-
expect(parseCli(["act", "."]).args).toEqual(["."])
|
|
55
|
-
expectUsageError(["act", "one", "two"], "agency act")
|
|
56
|
-
expectUsageError(["act", ".", "--task", "example"], "agency act")
|
|
57
|
-
expectUsageError(["act", "--phase", "build"], "agency act")
|
|
58
|
-
expectUsageError(
|
|
59
|
-
["act", "--epic", "roadmap", "--task", "example"],
|
|
60
|
-
"agency act",
|
|
61
|
-
)
|
|
62
|
-
expectUsageError(["act", "--dry-run", "--json"], "agency act")
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test("accepts review creation and refresh while enforcing one source", () => {
|
|
66
|
-
expect(
|
|
67
|
-
parseCli([
|
|
68
|
-
"task",
|
|
69
|
-
"create",
|
|
70
|
-
"review-it",
|
|
71
|
-
"--review",
|
|
72
|
-
"agency",
|
|
73
|
-
"--pull-request",
|
|
74
|
-
"42",
|
|
75
|
-
]).values,
|
|
76
|
-
).toMatchObject({ review: "agency", "pull-request": "42" })
|
|
77
|
-
expect(() =>
|
|
78
|
-
parseCli([
|
|
79
|
-
"task",
|
|
80
|
-
"create",
|
|
81
|
-
"review-it",
|
|
82
|
-
"--review",
|
|
83
|
-
"agency",
|
|
84
|
-
"--ref",
|
|
85
|
-
"feature/review",
|
|
86
|
-
]),
|
|
87
|
-
).not.toThrow()
|
|
88
|
-
expect(() =>
|
|
89
|
-
parseCli([
|
|
90
|
-
"review",
|
|
91
|
-
"refresh",
|
|
92
|
-
"review-it",
|
|
93
|
-
"--if-revision",
|
|
94
|
-
"a".repeat(64),
|
|
95
|
-
]),
|
|
96
|
-
).not.toThrow()
|
|
97
|
-
expect(() =>
|
|
98
|
-
parseCli([
|
|
99
|
-
"task",
|
|
100
|
-
"create",
|
|
101
|
-
"review-it",
|
|
102
|
-
"--review",
|
|
103
|
-
"agency",
|
|
104
|
-
"--pull-request",
|
|
105
|
-
"42",
|
|
106
|
-
"--ref",
|
|
107
|
-
"feature/review",
|
|
108
|
-
]),
|
|
109
|
-
).toThrow("exactly one")
|
|
110
|
-
for (const extra of [
|
|
111
|
-
["--ref", "feature/review", "--repo", "agency"],
|
|
112
|
-
["--ref", "feature/review", "--multi-phase"],
|
|
113
|
-
]) {
|
|
114
|
-
expect(() =>
|
|
115
|
-
parseCli([
|
|
116
|
-
"task",
|
|
117
|
-
"create",
|
|
118
|
-
"review-it",
|
|
119
|
-
"--review",
|
|
120
|
-
"agency",
|
|
121
|
-
...extra,
|
|
122
|
-
]),
|
|
123
|
-
).toThrow("cannot be combined")
|
|
124
|
-
}
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
test("accepts every documented orchestration recipe command", () => {
|
|
128
|
-
for (const args of orchestrationRecipes) {
|
|
129
|
-
expect(() => parseCli(args)).not.toThrow()
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test("rejects misspelled and command-inapplicable options", () => {
|
|
134
|
-
expectUsageError(["task", "list", "--josn"], "agency task")
|
|
135
|
-
expectUsageError(
|
|
136
|
-
["task", "list", "--repo", "agency"],
|
|
137
|
-
"agency task list [filters] [--json]",
|
|
138
|
-
)
|
|
139
|
-
expectUsageError(["status", "--draft"], "agency status [filters] [--json]")
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
test("rejects duplicate scalar, boolean, and single-value multiple options", () => {
|
|
143
|
-
for (const args of [
|
|
144
|
-
["status", "--json", "--json"],
|
|
145
|
-
["task", "create", "example", "--repo", "one", "--repo", "two"],
|
|
146
|
-
[
|
|
147
|
-
"task",
|
|
148
|
-
"create",
|
|
149
|
-
"example",
|
|
150
|
-
"--repo",
|
|
151
|
-
"one",
|
|
152
|
-
"--base",
|
|
153
|
-
"a",
|
|
154
|
-
"--base",
|
|
155
|
-
"b",
|
|
156
|
-
],
|
|
157
|
-
["status", "-s", "--silent"],
|
|
158
|
-
]) {
|
|
159
|
-
expect(() => parseCli(args)).toThrow("may only be specified once")
|
|
160
|
-
}
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
test("preserves explicitly repeatable options", () => {
|
|
164
|
-
expect(
|
|
165
|
-
parseCli([
|
|
166
|
-
"epic",
|
|
167
|
-
"create",
|
|
168
|
-
"delivery",
|
|
169
|
-
"--ticket-url",
|
|
170
|
-
"https://example.com",
|
|
171
|
-
"--repo",
|
|
172
|
-
"one:main",
|
|
173
|
-
"--repo",
|
|
174
|
-
"two:main",
|
|
175
|
-
]).values.repo,
|
|
176
|
-
).toEqual(["one:main", "two:main"])
|
|
177
|
-
expect(
|
|
178
|
-
parseCli([
|
|
179
|
-
"phase",
|
|
180
|
-
"create",
|
|
181
|
-
"task",
|
|
182
|
-
"phase",
|
|
183
|
-
"--repo",
|
|
184
|
-
"one",
|
|
185
|
-
"--branch",
|
|
186
|
-
"feature",
|
|
187
|
-
"--base",
|
|
188
|
-
"main",
|
|
189
|
-
"--reference",
|
|
190
|
-
"two:main",
|
|
191
|
-
"--reference",
|
|
192
|
-
"three:main",
|
|
193
|
-
"--depends-on",
|
|
194
|
-
"first",
|
|
195
|
-
"--depends-on",
|
|
196
|
-
"second",
|
|
197
|
-
]).values,
|
|
198
|
-
).toMatchObject({
|
|
199
|
-
reference: ["two:main", "three:main"],
|
|
200
|
-
"depends-on": ["first", "second"],
|
|
201
|
-
})
|
|
202
|
-
expect(
|
|
203
|
-
parseCli([
|
|
204
|
-
"archive",
|
|
205
|
-
"list",
|
|
206
|
-
"--kind",
|
|
207
|
-
"task",
|
|
208
|
-
"--kind",
|
|
209
|
-
"phase",
|
|
210
|
-
"--status",
|
|
211
|
-
"done",
|
|
212
|
-
"--repository",
|
|
213
|
-
"agency",
|
|
214
|
-
]).values,
|
|
215
|
-
).toMatchObject({
|
|
216
|
-
kind: ["task", "phase"],
|
|
217
|
-
status: ["done"],
|
|
218
|
-
repository: ["agency"],
|
|
219
|
-
})
|
|
220
|
-
expect(
|
|
221
|
-
parseCli(["restore", "task", "example", "--dry-run"]).values,
|
|
222
|
-
).toMatchObject({ "dry-run": true })
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
test("parses composable view filters", () => {
|
|
226
|
-
expect(
|
|
227
|
-
parseCli([
|
|
228
|
-
"task",
|
|
229
|
-
"list",
|
|
230
|
-
"--status",
|
|
231
|
-
"open",
|
|
232
|
-
"--status",
|
|
233
|
-
"working",
|
|
234
|
-
"--repository",
|
|
235
|
-
"agency",
|
|
236
|
-
"--ready",
|
|
237
|
-
"--pr",
|
|
238
|
-
]).values,
|
|
239
|
-
).toMatchObject({
|
|
240
|
-
status: ["open", "working"],
|
|
241
|
-
repository: ["agency"],
|
|
242
|
-
ready: true,
|
|
243
|
-
pr: true,
|
|
244
|
-
})
|
|
245
|
-
expect(parseCli(["status", "--no-pr"]).values["no-pr"]).toBe(true)
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
test("parses addressable resource maintenance commands", () => {
|
|
249
|
-
for (const args of [
|
|
250
|
-
["doctor", "--json"],
|
|
251
|
-
["repo", "materialize", "--help"],
|
|
252
|
-
["repo", "show", "agency", "--json"],
|
|
253
|
-
["repo", "materialize", "agency", "--json"],
|
|
254
|
-
["repo", "fetch", "agency"],
|
|
255
|
-
["repo", "remove", "agency"],
|
|
256
|
-
["repo", "unlink", "agency"],
|
|
257
|
-
["repo", "rename", "agency", "renamed"],
|
|
258
|
-
["repo", "remote", "agency", "https://example.com/repo.git"],
|
|
259
|
-
["repo", "verify", "agency"],
|
|
260
|
-
["workbase", "show", "primary", "--json"],
|
|
261
|
-
["workbase", "init", "new-workbase", "--json"],
|
|
262
|
-
["workbase", "name", "primary", "renamed"],
|
|
263
|
-
["workbase", "name", "primary", "--clear"],
|
|
264
|
-
]) {
|
|
265
|
-
expect(() => parseCli(args)).not.toThrow()
|
|
266
|
-
}
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
test("validates view filter values and conflicts", () => {
|
|
270
|
-
expect(() => parseCli(["epic", "list", "--status", "invalid"])).toThrow(
|
|
271
|
-
"Invalid '--status' value",
|
|
272
|
-
)
|
|
273
|
-
expect(() =>
|
|
274
|
-
parseCli(["phase", "list", "task", "--ready", "--blocked"]),
|
|
275
|
-
).toThrow("cannot be combined")
|
|
276
|
-
expect(() => parseCli(["status", "--pr", "--no-pr"])).toThrow(
|
|
277
|
-
"cannot be combined",
|
|
278
|
-
)
|
|
279
|
-
expect(() => parseCli(["archive", "list", "--status", "invalid"])).toThrow(
|
|
280
|
-
"Invalid '--status' value",
|
|
281
|
-
)
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
test("enforces exact maximum positional arity for every leaf command", () => {
|
|
285
|
-
for (const [args, usage] of [
|
|
286
|
-
[["init", "one", "two"], "agency init"],
|
|
287
|
-
[["workbase", "init", "one", "two"], "agency workbase init"],
|
|
288
|
-
[["workbase", "add", "one", "two"], "agency workbase add"],
|
|
289
|
-
[["workbase", "list", "extra"], "agency workbase list"],
|
|
290
|
-
[["integration", "status", "extra"], "agency integration status"],
|
|
291
|
-
[["integration", "sync", "extra"], "agency integration sync"],
|
|
292
|
-
[["repo", "add", "a", "b", "extra"], "agency repo add"],
|
|
293
|
-
[["repo", "link", "a", "b", "extra"], "agency repo link"],
|
|
294
|
-
[["repo", "materialize", "a", "extra"], "agency repo materialize"],
|
|
295
|
-
[["repo", "list", "extra"], "agency repo list"],
|
|
296
|
-
[
|
|
297
|
-
[
|
|
298
|
-
"epic",
|
|
299
|
-
"create",
|
|
300
|
-
"one",
|
|
301
|
-
"two",
|
|
302
|
-
"--ticket-url",
|
|
303
|
-
"url",
|
|
304
|
-
"--repo",
|
|
305
|
-
"repo:main",
|
|
306
|
-
],
|
|
307
|
-
"agency epic create",
|
|
308
|
-
],
|
|
309
|
-
[["epic", "list", "extra"], "agency epic list"],
|
|
310
|
-
[["epic", "show", "one", "two"], "agency epic show"],
|
|
311
|
-
[["task", "new", "one", "two"], "agency task new"],
|
|
312
|
-
[
|
|
313
|
-
["task", "create", "one", "two", "--repo", "repo"],
|
|
314
|
-
"agency task create",
|
|
315
|
-
],
|
|
316
|
-
[["task", "list", "extra"], "agency task list"],
|
|
317
|
-
[["task", "show", "one", "two"], "agency task show"],
|
|
318
|
-
[["task", "status", "one", "open", "extra"], "agency task status"],
|
|
319
|
-
[
|
|
320
|
-
[
|
|
321
|
-
"phase",
|
|
322
|
-
"create",
|
|
323
|
-
"task",
|
|
324
|
-
"phase",
|
|
325
|
-
"extra",
|
|
326
|
-
"--repo",
|
|
327
|
-
"repo",
|
|
328
|
-
"--branch",
|
|
329
|
-
"branch",
|
|
330
|
-
"--base",
|
|
331
|
-
"main",
|
|
332
|
-
],
|
|
333
|
-
"agency phase create",
|
|
334
|
-
],
|
|
335
|
-
[["phase", "list", "one", "two"], "agency phase list"],
|
|
336
|
-
[["phase", "show", "one", "two", "three"], "agency phase show"],
|
|
337
|
-
[
|
|
338
|
-
["phase", "status", "one", "two", "open", "extra"],
|
|
339
|
-
"agency phase status",
|
|
340
|
-
],
|
|
341
|
-
[["archive", "epic", "one", "two"], "agency archive epic"],
|
|
342
|
-
[["archive", "task", "one", "two"], "agency archive task"],
|
|
343
|
-
[["archive", "tasks", "one"], "agency archive tasks"],
|
|
344
|
-
[["archive", "phase", "one", "two", "three"], "agency archive phase"],
|
|
345
|
-
[["archive", "list", "extra"], "agency archive list"],
|
|
346
|
-
[
|
|
347
|
-
["archive", "show", "task", "one", "extra", "more"],
|
|
348
|
-
"agency archive show",
|
|
349
|
-
],
|
|
350
|
-
[["restore", "epic", "one", "two"], "agency restore epic"],
|
|
351
|
-
[["restore", "task", "one", "two"], "agency restore task"],
|
|
352
|
-
[["restore", "phase", "one", "two", "three"], "agency restore phase"],
|
|
353
|
-
[["work", "one", "two"], "agency work"],
|
|
354
|
-
[["status", "extra"], "agency status"],
|
|
355
|
-
[["validate", "one", "two"], "agency validate"],
|
|
356
|
-
[["context", "one", "two"], "agency context"],
|
|
357
|
-
[["graph", "extra"], "agency graph"],
|
|
358
|
-
[["next", "extra"], "agency next"],
|
|
359
|
-
[["sync", "one", "two", "three"], "agency sync"],
|
|
360
|
-
] as const) {
|
|
361
|
-
expectUsageError([...args], usage)
|
|
362
|
-
}
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
test("parses readiness selection and explicit guard overrides", () => {
|
|
366
|
-
expect(parseCli(["next", "--select", "--json"])).toMatchObject({
|
|
367
|
-
commandName: "next",
|
|
368
|
-
values: { select: true, json: true },
|
|
369
|
-
})
|
|
370
|
-
expect(parseCli(["work", "example", "--force"])).toMatchObject({
|
|
371
|
-
commandName: "work",
|
|
372
|
-
values: { force: true },
|
|
373
|
-
})
|
|
374
|
-
expect(parseCli(["work", "prepare", "example", "--force"])).toMatchObject({
|
|
375
|
-
commandName: "work",
|
|
376
|
-
args: ["prepare", "example"],
|
|
377
|
-
values: { force: true },
|
|
378
|
-
})
|
|
379
|
-
})
|
|
380
|
-
|
|
381
|
-
test("preserves every argument after pr without parsing it", () => {
|
|
382
|
-
const args = ["create", "--title", "two words", "--", "--literal"]
|
|
383
|
-
expect(parseCli(["--cwd", "/workbase", "pr", ...args])).toEqual({
|
|
384
|
-
commandName: "pr",
|
|
385
|
-
commandPath: "pr",
|
|
386
|
-
args,
|
|
387
|
-
passthrough: true,
|
|
388
|
-
values: { cwd: "/workbase" },
|
|
389
|
-
})
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
test("parses task-aware pr create without routing it to passthrough", () => {
|
|
393
|
-
expect(
|
|
394
|
-
parseCli([
|
|
395
|
-
"pr",
|
|
396
|
-
"create",
|
|
397
|
-
"ship",
|
|
398
|
-
"release",
|
|
399
|
-
"--draft",
|
|
400
|
-
"--force",
|
|
401
|
-
"--json",
|
|
402
|
-
]),
|
|
403
|
-
).toEqual({
|
|
404
|
-
commandName: "pr",
|
|
405
|
-
commandPath: "pr/create",
|
|
406
|
-
args: ["create", "ship", "release"],
|
|
407
|
-
values: { draft: true, force: true, json: true },
|
|
408
|
-
})
|
|
409
|
-
const selected = parseCli(["pr", "create", "--task", "ship"])
|
|
410
|
-
expect(selected).toMatchObject({
|
|
411
|
-
args: ["create", "ship"],
|
|
412
|
-
})
|
|
413
|
-
expect(selected.passthrough).toBeUndefined()
|
|
414
|
-
expect(
|
|
415
|
-
parseCli([
|
|
416
|
-
"pr",
|
|
417
|
-
"create",
|
|
418
|
-
"ship",
|
|
419
|
-
"--title",
|
|
420
|
-
"Ship it",
|
|
421
|
-
"--head",
|
|
422
|
-
"task/ship",
|
|
423
|
-
"--base",
|
|
424
|
-
"main",
|
|
425
|
-
"--label",
|
|
426
|
-
"ai-assisted",
|
|
427
|
-
"--label",
|
|
428
|
-
"product-area:platform",
|
|
429
|
-
]),
|
|
430
|
-
).toMatchObject({
|
|
431
|
-
args: ["create", "ship"],
|
|
432
|
-
values: {
|
|
433
|
-
title: "Ship it",
|
|
434
|
-
head: "task/ship",
|
|
435
|
-
base: "main",
|
|
436
|
-
label: ["ai-assisted", "product-area:platform"],
|
|
437
|
-
},
|
|
438
|
-
})
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
test("parses explicit dry-run reconciliation", () => {
|
|
442
|
-
expect(parseCli(["sync"])).toMatchObject({
|
|
443
|
-
commandName: "sync",
|
|
444
|
-
values: {},
|
|
445
|
-
})
|
|
446
|
-
expect(parseCli(["sync", "--dry-run", "--json"])).toMatchObject({
|
|
447
|
-
commandName: "sync",
|
|
448
|
-
values: { "dry-run": true, json: true },
|
|
449
|
-
})
|
|
450
|
-
expect(parseCli(["sync", "ship", "release", "--json"])).toMatchObject({
|
|
451
|
-
commandName: "sync",
|
|
452
|
-
args: ["ship", "release"],
|
|
453
|
-
values: { json: true },
|
|
454
|
-
})
|
|
455
|
-
expect(() => parseCli(["sync", "--apply"])).toThrow("Unknown option")
|
|
456
|
-
})
|
|
457
|
-
|
|
458
|
-
test("accepts archive dry-run", () => {
|
|
459
|
-
expect(parseCli(["archive", ".", "--dry-run"])).toMatchObject({
|
|
460
|
-
commandName: "archive",
|
|
461
|
-
args: ["."],
|
|
462
|
-
values: { "dry-run": true },
|
|
463
|
-
})
|
|
464
|
-
expect(parseCli(["archive", "task", "example", "--dry-run"])).toMatchObject(
|
|
465
|
-
{
|
|
466
|
-
commandName: "archive",
|
|
467
|
-
values: { "dry-run": true },
|
|
468
|
-
},
|
|
469
|
-
)
|
|
470
|
-
expect(parseCli(["archive", "tasks", "--dry-run", "--json"])).toMatchObject(
|
|
471
|
-
{
|
|
472
|
-
commandName: "archive",
|
|
473
|
-
args: ["tasks"],
|
|
474
|
-
values: { "dry-run": true, json: true },
|
|
475
|
-
},
|
|
476
|
-
)
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
test("rejects removed claim protocol commands", () => {
|
|
480
|
-
for (const command of ["claim", "release", "finish"]) {
|
|
481
|
-
expect(() => parseCli([command])).toThrow(`Unknown command '${command}'`)
|
|
482
|
-
}
|
|
483
|
-
expect(() =>
|
|
484
|
-
parseCli([
|
|
485
|
-
"task",
|
|
486
|
-
"status",
|
|
487
|
-
"example",
|
|
488
|
-
"working",
|
|
489
|
-
"--no-pull-request",
|
|
490
|
-
"--summary",
|
|
491
|
-
"Not done",
|
|
492
|
-
]),
|
|
493
|
-
).toThrow("valid only with a done status")
|
|
494
|
-
expect(() =>
|
|
495
|
-
parseCli([
|
|
496
|
-
"phase",
|
|
497
|
-
"status",
|
|
498
|
-
"task",
|
|
499
|
-
"phase",
|
|
500
|
-
"done",
|
|
501
|
-
"--summary",
|
|
502
|
-
"Missing explicit flag",
|
|
503
|
-
]),
|
|
504
|
-
).toThrow("require '--no-pull-request'")
|
|
505
|
-
})
|
|
506
|
-
|
|
507
|
-
test("accepts valid mutation revisions and rejects malformed hashes", () => {
|
|
508
|
-
const revision = "a".repeat(64)
|
|
509
|
-
expect(
|
|
510
|
-
parseCli([
|
|
511
|
-
"task",
|
|
512
|
-
"move",
|
|
513
|
-
"example",
|
|
514
|
-
"--no-epic",
|
|
515
|
-
"--if-revision",
|
|
516
|
-
revision,
|
|
517
|
-
]),
|
|
518
|
-
).toMatchObject({ values: { "if-revision": revision } })
|
|
519
|
-
expect(() =>
|
|
520
|
-
parseCli([
|
|
521
|
-
"phase",
|
|
522
|
-
"rename",
|
|
523
|
-
"task",
|
|
524
|
-
"phase",
|
|
525
|
-
"renamed",
|
|
526
|
-
"--if-revision",
|
|
527
|
-
"stale",
|
|
528
|
-
]),
|
|
529
|
-
).toThrow("64-character SHA-256 hash")
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
test("accepts context projections and keeps compact command-local", () => {
|
|
533
|
-
expect(parseCli(["context", ".", "--json", "--compact"])).toMatchObject({
|
|
534
|
-
commandName: "context",
|
|
535
|
-
args: ["."],
|
|
536
|
-
values: { json: true, compact: true },
|
|
537
|
-
})
|
|
538
|
-
expectUsageError(["status", "--compact"], "agency status")
|
|
539
|
-
expect(parseCli(["context", ".", "--json", "--full"])).toMatchObject({
|
|
540
|
-
commandName: "context",
|
|
541
|
-
args: ["."],
|
|
542
|
-
values: { json: true, full: true },
|
|
543
|
-
})
|
|
544
|
-
expectUsageError(["context", ".", "--compact", "--full"], "agency context")
|
|
545
|
-
expectUsageError(["status", "--full"], "agency status")
|
|
546
|
-
})
|
|
547
|
-
|
|
548
|
-
test("accepts work preparation options only for the prepare subcommand", () => {
|
|
549
|
-
expect(
|
|
550
|
-
parseCli(["work", "prepare", "tasks/example", "--dry-run", "--json"]),
|
|
551
|
-
).toMatchObject({
|
|
552
|
-
commandName: "work",
|
|
553
|
-
args: ["prepare", "tasks/example"],
|
|
554
|
-
values: { "dry-run": true, json: true },
|
|
555
|
-
})
|
|
556
|
-
expect(() => parseCli(["work", "example", "--dry-run"])).toThrow(
|
|
557
|
-
"only valid with 'agency work prepare'",
|
|
558
|
-
)
|
|
559
|
-
expect(() => parseCli(["work", "prepare", "--opencode"])).toThrow(
|
|
560
|
-
"cannot be combined",
|
|
561
|
-
)
|
|
562
|
-
expect(() => parseCli(["work", "prepare", "first", "second"])).toThrow(
|
|
563
|
-
"Expected 0-2 positional arguments",
|
|
564
|
-
)
|
|
565
|
-
expect(() =>
|
|
566
|
-
parseCli(["work", "prepare", "example", "--task", "other"]),
|
|
567
|
-
).toThrow("Entity selector options cannot be combined")
|
|
568
|
-
expect(() => parseCli(["work", "prepare", "--phase", "build"])).toThrow(
|
|
569
|
-
"requires '--task'",
|
|
570
|
-
)
|
|
571
|
-
})
|
|
572
|
-
|
|
573
|
-
test("parses worktree lifecycle commands and selectors", () => {
|
|
574
|
-
expect(parseCli(["worktree", "list", "--json"])).toMatchObject({
|
|
575
|
-
commandName: "worktree",
|
|
576
|
-
args: ["list"],
|
|
577
|
-
values: { json: true },
|
|
578
|
-
})
|
|
579
|
-
expect(
|
|
580
|
-
parseCli([
|
|
581
|
-
"worktree",
|
|
582
|
-
"rebuild",
|
|
583
|
-
"--task",
|
|
584
|
-
"example",
|
|
585
|
-
"--phase",
|
|
586
|
-
"verify",
|
|
587
|
-
"--dry-run",
|
|
588
|
-
"--force",
|
|
589
|
-
]),
|
|
590
|
-
).toMatchObject({
|
|
591
|
-
commandName: "worktree",
|
|
592
|
-
args: ["rebuild", "example", "verify"],
|
|
593
|
-
values: {
|
|
594
|
-
task: "example",
|
|
595
|
-
phase: "verify",
|
|
596
|
-
"dry-run": true,
|
|
597
|
-
force: true,
|
|
598
|
-
},
|
|
599
|
-
})
|
|
600
|
-
expectUsageError(
|
|
601
|
-
["worktree", "inspect", "example", "--dry-run"],
|
|
602
|
-
"agency worktree inspect",
|
|
603
|
-
)
|
|
604
|
-
expect(() => parseCli(["worktree", "repair", "--phase", "verify"])).toThrow(
|
|
605
|
-
"requires '--task'",
|
|
606
|
-
)
|
|
607
|
-
})
|
|
608
|
-
|
|
609
|
-
test("parses push without accepting an alternate target", () => {
|
|
610
|
-
expect(parseCli(["push", "--json"])).toMatchObject({
|
|
611
|
-
commandName: "push",
|
|
612
|
-
args: [],
|
|
613
|
-
values: { json: true },
|
|
614
|
-
})
|
|
615
|
-
expectUsageError(["push", "example"], "agency push")
|
|
616
|
-
})
|
|
617
|
-
|
|
618
|
-
test("accepts agent selection and command inspection for work", () => {
|
|
619
|
-
expect(
|
|
620
|
-
parseCli([
|
|
621
|
-
"work",
|
|
622
|
-
"example",
|
|
623
|
-
"--agent",
|
|
624
|
-
"custom",
|
|
625
|
-
"--auto",
|
|
626
|
-
"--print-command",
|
|
627
|
-
]),
|
|
628
|
-
).toMatchObject({
|
|
629
|
-
commandName: "work",
|
|
630
|
-
args: ["example"],
|
|
631
|
-
values: { agent: "custom", auto: true, "print-command": true },
|
|
632
|
-
})
|
|
633
|
-
expect(() =>
|
|
634
|
-
parseCli(["work", "example", "--agent", "custom", "--claude"]),
|
|
635
|
-
).toThrow("cannot be combined")
|
|
636
|
-
expect(() => parseCli(["work", "prepare", "--print-command"])).toThrow(
|
|
637
|
-
"cannot be combined",
|
|
638
|
-
)
|
|
639
|
-
expect(() => parseCli(["work", "prepare", "--auto"])).toThrow(
|
|
640
|
-
"cannot be combined",
|
|
641
|
-
)
|
|
642
|
-
})
|
|
643
|
-
|
|
644
|
-
test("accepts work launch options on new entities", () => {
|
|
645
|
-
expect(
|
|
646
|
-
parseCli(["task", "new", "example", "--work", "--auto"]),
|
|
647
|
-
).toMatchObject({
|
|
648
|
-
commandName: "task",
|
|
649
|
-
args: ["new", "example"],
|
|
650
|
-
values: { work: true, auto: true },
|
|
651
|
-
})
|
|
652
|
-
expect(
|
|
653
|
-
parseCli([
|
|
654
|
-
"epic",
|
|
655
|
-
"new",
|
|
656
|
-
"delivery",
|
|
657
|
-
"--ticket-url",
|
|
658
|
-
"https://example.com/delivery",
|
|
659
|
-
"--repo",
|
|
660
|
-
"agency:main",
|
|
661
|
-
"--work",
|
|
662
|
-
]),
|
|
663
|
-
).toMatchObject({ commandName: "epic", args: ["new", "delivery"] })
|
|
664
|
-
expect(
|
|
665
|
-
parseCli([
|
|
666
|
-
"phase",
|
|
667
|
-
"new",
|
|
668
|
-
"delivery",
|
|
669
|
-
"implementation",
|
|
670
|
-
"--repo",
|
|
671
|
-
"agency",
|
|
672
|
-
"--branch",
|
|
673
|
-
"task/implementation",
|
|
674
|
-
"--base",
|
|
675
|
-
"main",
|
|
676
|
-
"--work",
|
|
677
|
-
]),
|
|
678
|
-
).toMatchObject({
|
|
679
|
-
commandName: "phase",
|
|
680
|
-
args: ["new", "delivery", "implementation"],
|
|
681
|
-
})
|
|
682
|
-
expect(() => parseCli(["task", "new", "example", "--auto"])).toThrow(
|
|
683
|
-
"Option '--auto' requires '--work'",
|
|
684
|
-
)
|
|
685
|
-
expect(() =>
|
|
686
|
-
parseCli(["task", "new", "example", "--work", "--json"]),
|
|
687
|
-
).toThrow("cannot be combined")
|
|
688
|
-
expectUsageError(
|
|
689
|
-
["task", "create", "example", "--repo", "agency", "--work"],
|
|
690
|
-
"agency task create",
|
|
691
|
-
)
|
|
692
|
-
})
|
|
693
|
-
|
|
694
|
-
test("accepts repeatable graph filters and rejects output conflicts", () => {
|
|
695
|
-
expect(
|
|
696
|
-
parseCli([
|
|
697
|
-
"graph",
|
|
698
|
-
"--json",
|
|
699
|
-
"--status",
|
|
700
|
-
"open",
|
|
701
|
-
"--status",
|
|
702
|
-
"working",
|
|
703
|
-
"--repository",
|
|
704
|
-
"agency",
|
|
705
|
-
"--kind",
|
|
706
|
-
"task",
|
|
707
|
-
"--kind",
|
|
708
|
-
"phase",
|
|
709
|
-
"--include",
|
|
710
|
-
"bodies",
|
|
711
|
-
"--include",
|
|
712
|
-
"git",
|
|
713
|
-
]).values,
|
|
714
|
-
).toMatchObject({
|
|
715
|
-
json: true,
|
|
716
|
-
status: ["open", "working"],
|
|
717
|
-
repository: ["agency"],
|
|
718
|
-
kind: ["task", "phase"],
|
|
719
|
-
include: ["bodies", "git"],
|
|
720
|
-
})
|
|
721
|
-
expect(() => parseCli(["graph", "--json", "--jsonl"])).toThrow(
|
|
722
|
-
"cannot be combined",
|
|
723
|
-
)
|
|
724
|
-
expect(() => parseCli(["graph", "--ready", "--blocked"])).toThrow(
|
|
725
|
-
"cannot be combined",
|
|
726
|
-
)
|
|
727
|
-
for (const [option, value] of [
|
|
728
|
-
["status", "started"],
|
|
729
|
-
["kind", "worktree"],
|
|
730
|
-
["include", "secrets"],
|
|
731
|
-
] as const) {
|
|
732
|
-
expect(() => parseCli(["graph", `--${option}`, value])).toThrow(
|
|
733
|
-
`Invalid '--${option}' value`,
|
|
734
|
-
)
|
|
735
|
-
}
|
|
736
|
-
})
|
|
737
|
-
|
|
738
|
-
test("reports unknown subcommands with parent usage", () => {
|
|
739
|
-
expect(() => parseCli(["task", "crate"])).toThrow(
|
|
740
|
-
"Unknown subcommand 'crate'",
|
|
741
|
-
)
|
|
742
|
-
expectUsageError(
|
|
743
|
-
["task", "crate"],
|
|
744
|
-
"agency task <new|create|handoff|list|show|status|update|rename|move|dependency>",
|
|
745
|
-
)
|
|
746
|
-
})
|
|
747
|
-
|
|
748
|
-
test("parses investigation creation and explicit handoff commands", () => {
|
|
749
|
-
expect(
|
|
750
|
-
parseCli([
|
|
751
|
-
"task",
|
|
752
|
-
"create",
|
|
753
|
-
"investigate",
|
|
754
|
-
"--purpose",
|
|
755
|
-
"investigation",
|
|
756
|
-
"--repo",
|
|
757
|
-
"agency",
|
|
758
|
-
]),
|
|
759
|
-
).toMatchObject({
|
|
760
|
-
args: ["create", "investigate"],
|
|
761
|
-
values: { purpose: "investigation", repo: ["agency"] },
|
|
762
|
-
})
|
|
763
|
-
expect(
|
|
764
|
-
parseCli([
|
|
765
|
-
"task",
|
|
766
|
-
"handoff",
|
|
767
|
-
"investigate",
|
|
768
|
-
"implement",
|
|
769
|
-
"--source-phase",
|
|
770
|
-
"evidence",
|
|
771
|
-
"--repo",
|
|
772
|
-
"agency",
|
|
773
|
-
"--json",
|
|
774
|
-
]),
|
|
775
|
-
).toMatchObject({
|
|
776
|
-
args: ["handoff", "investigate", "implement"],
|
|
777
|
-
values: {
|
|
778
|
-
"source-phase": "evidence",
|
|
779
|
-
repo: ["agency"],
|
|
780
|
-
json: true,
|
|
781
|
-
},
|
|
782
|
-
})
|
|
783
|
-
expect(() =>
|
|
784
|
-
parseCli([
|
|
785
|
-
"task",
|
|
786
|
-
"create",
|
|
787
|
-
"investigate",
|
|
788
|
-
"--purpose",
|
|
789
|
-
"unknown",
|
|
790
|
-
"--repo",
|
|
791
|
-
"agency",
|
|
792
|
-
]),
|
|
793
|
-
).toThrow("Invalid '--purpose' value")
|
|
794
|
-
})
|
|
795
|
-
|
|
796
|
-
test("parses graph mutation commands and rejects unsafe ambiguity", () => {
|
|
797
|
-
expect(
|
|
798
|
-
parseCli([
|
|
799
|
-
"task",
|
|
800
|
-
"update",
|
|
801
|
-
"example",
|
|
802
|
-
"--description",
|
|
803
|
-
"Revised",
|
|
804
|
-
"--reference",
|
|
805
|
-
"docs:main",
|
|
806
|
-
"--reference",
|
|
807
|
-
"api:main",
|
|
808
|
-
"--clear-pr",
|
|
809
|
-
]),
|
|
810
|
-
).toMatchObject({
|
|
811
|
-
args: ["update", "example"],
|
|
812
|
-
values: {
|
|
813
|
-
description: "Revised",
|
|
814
|
-
reference: ["docs:main", "api:main"],
|
|
815
|
-
"clear-pr": true,
|
|
816
|
-
},
|
|
817
|
-
})
|
|
818
|
-
expect(
|
|
819
|
-
parseCli(["task", "move", "example", "--no-epic"]).values,
|
|
820
|
-
).toMatchObject({
|
|
821
|
-
"no-epic": true,
|
|
822
|
-
})
|
|
823
|
-
expect(parseCli(["phase", "rename", "task", "old", "new"]).args).toEqual([
|
|
824
|
-
"rename",
|
|
825
|
-
"task",
|
|
826
|
-
"old",
|
|
827
|
-
"new",
|
|
828
|
-
])
|
|
829
|
-
expect(() => parseCli(["task", "update", "example"])).toThrow(
|
|
830
|
-
"At least one update option",
|
|
831
|
-
)
|
|
832
|
-
expect(() =>
|
|
833
|
-
parseCli(["task", "move", "example", "--epic", "one", "--no-epic"]),
|
|
834
|
-
).toThrow("cannot be combined")
|
|
835
|
-
expect(() => parseCli(["task", "dependency", "replace", "a", "b"])).toThrow(
|
|
836
|
-
"must be 'add' or 'remove'",
|
|
837
|
-
)
|
|
838
|
-
})
|
|
839
|
-
|
|
840
|
-
test("rejects required-option omissions and explicit conflicts", () => {
|
|
841
|
-
expect(() => parseCli(["task", "create", "example"])).toThrow(
|
|
842
|
-
"--repo' or '--context-repo' is required",
|
|
843
|
-
)
|
|
844
|
-
for (const option of ["repo", "reference", "branch", "base"] as const) {
|
|
845
|
-
const value = option === "reference" ? "other:main" : "value"
|
|
846
|
-
expect(() =>
|
|
847
|
-
parseCli([
|
|
848
|
-
"task",
|
|
849
|
-
"create",
|
|
850
|
-
"example",
|
|
851
|
-
"--multi-phase",
|
|
852
|
-
`--${option}`,
|
|
853
|
-
value,
|
|
854
|
-
]),
|
|
855
|
-
).toThrow("cannot be combined")
|
|
856
|
-
}
|
|
857
|
-
expect(() =>
|
|
858
|
-
parseCli(["task", "new", "example", "--multi-phase", "--repo", "repo"]),
|
|
859
|
-
).toThrow("cannot be combined")
|
|
860
|
-
expect(() => parseCli(["work", "--opencode", "--claude"])).toThrow(
|
|
861
|
-
"cannot be combined",
|
|
862
|
-
)
|
|
863
|
-
expect(() => parseCli(["work", "task", "--epic", "epic"])).toThrow(
|
|
864
|
-
"cannot be combined",
|
|
865
|
-
)
|
|
866
|
-
expect(() => parseCli(["status", "--silent", "--verbose"])).toThrow(
|
|
867
|
-
"cannot be combined",
|
|
868
|
-
)
|
|
869
|
-
})
|
|
870
|
-
|
|
871
|
-
test("accepts the global interaction control on every command", () => {
|
|
872
|
-
expect(parseCli(["--no-input", "task", "new"]).values["no-input"]).toBe(
|
|
873
|
-
true,
|
|
874
|
-
)
|
|
875
|
-
expect(parseCli(["work", "--no-input"]).values["no-input"]).toBe(true)
|
|
876
|
-
expect(parseCli(["validate", "--no-input"]).values["no-input"]).toBe(true)
|
|
877
|
-
expect(parseCli(["status", "--no-input"]).values["no-input"]).toBe(true)
|
|
878
|
-
expect(
|
|
879
|
-
parseCli(["task", "create", "example", "--repo", "repo", "--no-input"])
|
|
880
|
-
.values["no-input"],
|
|
881
|
-
).toBe(true)
|
|
882
|
-
})
|
|
883
|
-
|
|
884
|
-
test("normalizes explicit entity selectors into command targets", () => {
|
|
885
|
-
expect(
|
|
886
|
-
parseCli([
|
|
887
|
-
"phase",
|
|
888
|
-
"status",
|
|
889
|
-
"done",
|
|
890
|
-
"--task",
|
|
891
|
-
"ship",
|
|
892
|
-
"--phase",
|
|
893
|
-
"release",
|
|
894
|
-
]),
|
|
895
|
-
).toMatchObject({
|
|
896
|
-
commandName: "phase",
|
|
897
|
-
args: ["status", "ship", "release", "done"],
|
|
898
|
-
})
|
|
899
|
-
expect(parseCli(["context", "--epic", "delivery"]).values.epic).toBe(
|
|
900
|
-
"delivery",
|
|
901
|
-
)
|
|
902
|
-
})
|
|
903
|
-
|
|
904
|
-
test("enforces explicit selector precedence and exclusions", () => {
|
|
905
|
-
expect(() =>
|
|
906
|
-
parseCli(["task", "show", "positional", "--task", "explicit"]),
|
|
907
|
-
).toThrow("cannot be combined with positional target IDs")
|
|
908
|
-
expect(() => parseCli(["context", "--phase", "release"])).toThrow(
|
|
909
|
-
"--phase' requires '--task",
|
|
910
|
-
)
|
|
911
|
-
expect(() =>
|
|
912
|
-
parseCli(["work", "--epic", "delivery", "--task", "ship"]),
|
|
913
|
-
).toThrow("cannot be combined with '--task'")
|
|
914
|
-
expect(() =>
|
|
915
|
-
parseCli(["status", "--workbase", "primary", "--cwd", "/tmp"]),
|
|
916
|
-
).toThrow("--workbase' and '--cwd' cannot be combined")
|
|
917
|
-
})
|
|
918
|
-
|
|
919
|
-
test("accepts explicit workbase context before or after commands", () => {
|
|
920
|
-
expect(
|
|
921
|
-
parseCli(["--workbase", "primary", "task", "list", "--no-input"]).values
|
|
922
|
-
.workbase,
|
|
923
|
-
).toBe("primary")
|
|
924
|
-
expect(parseCli(["status", "--cwd", "/tmp"]).values.cwd).toBe("/tmp")
|
|
925
|
-
expect(
|
|
926
|
-
parseCli(["--workbase=primary", "task", "list"]).values.workbase,
|
|
927
|
-
).toBe("primary")
|
|
928
|
-
expect(parseCli(["--cwd=/tmp", "status"]).values.cwd).toBe("/tmp")
|
|
929
|
-
})
|
|
930
|
-
|
|
931
|
-
test("rejects empty selectors", () => {
|
|
932
|
-
for (const args of [
|
|
933
|
-
["status", "--workbase="],
|
|
934
|
-
["status", "--cwd="],
|
|
935
|
-
["context", "--task="],
|
|
936
|
-
]) {
|
|
937
|
-
expect(() => parseCli(args)).toThrow("requires a non-empty value")
|
|
938
|
-
}
|
|
939
|
-
})
|
|
940
|
-
|
|
941
|
-
test("accepts grouped global short options before a command", () => {
|
|
942
|
-
const parsed = parseCli(["-sh", "task"])
|
|
943
|
-
expect(parsed.values).toMatchObject({ silent: true, help: true })
|
|
944
|
-
})
|
|
945
|
-
})
|