@markjaquith/agency 2.49.0 → 2.51.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 +56 -9
- package/cli.ts +56 -1
- package/package.json +1 -1
- package/schemas/agency-graph-v1.schema.json +142 -38
- package/src/cli-parser.test.ts +81 -0
- package/src/cli-parser.ts +78 -1
- package/src/cli.test.ts +4 -4
- package/src/commands/init.test.ts +2 -0
- package/src/commands/review.ts +38 -0
- package/src/commands/task.ts +27 -5
- package/src/commands/vcs.test.ts +75 -0
- package/src/commands/vcs.ts +72 -0
- package/src/commands/work.test.ts +2 -0
- package/src/commands/work.ts +2 -2
- package/src/commands/worktree.ts +1 -1
- package/src/graph-schema.test.ts +1 -1
- package/src/graph-schema.ts +36 -13
- package/src/protocol.ts +1 -0
- package/src/services/ArchiveService.test.ts +2 -2
- package/src/services/ArchiveService.ts +24 -0
- package/src/services/ClaimService.ts +3 -2
- package/src/services/ContextService.ts +118 -17
- package/src/services/DoctorService.ts +58 -7
- package/src/services/GraphMutationService.ts +5 -0
- package/src/services/GraphService.ts +119 -54
- package/src/services/PhaseService.ts +196 -70
- package/src/services/PullRequestService.test.ts +2 -2
- package/src/services/PullRequestService.ts +37 -33
- package/src/services/ReadinessService.ts +7 -3
- package/src/services/RepositoryService.test.ts +31 -1
- package/src/services/RepositoryService.ts +63 -31
- package/src/services/ReviewService.test.ts +472 -0
- package/src/services/ReviewService.ts +427 -0
- package/src/services/SyncService.test.ts +69 -2
- package/src/services/SyncService.ts +161 -90
- package/src/services/TaskPhaseService.test.ts +80 -0
- package/src/services/TaskService.ts +82 -9
- package/src/services/VcsMigrationService.test.ts +211 -0
- package/src/services/VcsMigrationService.ts +816 -0
- package/src/services/VersionControlService.test.ts +100 -0
- package/src/services/VersionControlService.ts +479 -0
- package/src/services/WorkbaseService.ts +7 -2
- package/src/services/WorktreeService.test.ts +88 -17
- package/src/services/WorktreeService.ts +865 -329
- package/src/test-utils.ts +12 -0
- package/src/work-view.ts +14 -6
- package/src/workbase/AGENTS.md +2 -2
- package/src/workbase/schemas.test.ts +57 -0
- package/src/workbase/schemas.ts +57 -0
- package/src/workbase/version-control.ts +5 -0
package/README.md
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Agency manages durable agentic work across repositories. Epics, tasks, and
|
|
4
4
|
phases live as Markdown documents in a filesystem-backed workbase. Repository
|
|
5
|
-
aliases and
|
|
6
|
-
or write.
|
|
5
|
+
aliases and managed workspaces provide each execution unit with the code it may
|
|
6
|
+
read or write.
|
|
7
7
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
10
|
- [Bun](https://bun.sh) 1.0 or newer
|
|
11
11
|
- Git
|
|
12
|
+
- [Jujutsu](https://jj-vcs.github.io/jj/) is preferred when available
|
|
12
13
|
- [GitHub CLI](https://cli.github.com/) for `agency pr create`
|
|
13
14
|
- OpenCode, Claude Code, or a configured runner for `agency work`
|
|
14
15
|
|
|
@@ -122,14 +123,15 @@ The plugin grants whole-workbase access dynamically, while the portable
|
|
|
122
123
|
reference advertises that context to agents. Bash and Agency operations must
|
|
123
124
|
still follow the write authority reported by `agency context`.
|
|
124
125
|
|
|
125
|
-
Repository aliases and canonical fetch remotes are
|
|
126
|
-
`agency.json`; local
|
|
126
|
+
Repository aliases, the version-control backend, and canonical fetch remotes are
|
|
127
|
+
declared in tracked `agency.json`; local clones and symlinks remain ignored under
|
|
127
128
|
`repos/{alias}`. A declaration contains no local path, symlink target, checkout,
|
|
128
129
|
or credential:
|
|
129
130
|
|
|
130
131
|
```json
|
|
131
132
|
{
|
|
132
133
|
"version": 2,
|
|
134
|
+
"vcs": "jj",
|
|
133
135
|
"repositories": {
|
|
134
136
|
"frontend": {
|
|
135
137
|
"remote": "git@example.com:team/frontend.git"
|
|
@@ -138,6 +140,29 @@ or credential:
|
|
|
138
140
|
}
|
|
139
141
|
```
|
|
140
142
|
|
|
143
|
+
New workbases select `"jj"` when the `jj` executable is available and otherwise
|
|
144
|
+
select `"git"`. Existing version 2 workbases without `vcs` remain Git workbases.
|
|
145
|
+
The selected backend is a workbase-level invariant: jj workbases initialize
|
|
146
|
+
managed clones with `jj git init` and create jj workspaces, while Git workbases
|
|
147
|
+
continue to use Git worktrees.
|
|
148
|
+
|
|
149
|
+
Inspect the current backend and migration readiness with:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
agency vcs status
|
|
153
|
+
agency vcs migrate jj # dry-run
|
|
154
|
+
agency vcs migrate jj --apply
|
|
155
|
+
agency vcs migrate git --apply
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Migration is workbase-wide and transactional. Agency locks every execution
|
|
159
|
+
unit, requires clean registered workspaces, blocks active claims and working or
|
|
160
|
+
delegated units, converts repository metadata, recreates checkout paths with the
|
|
161
|
+
target backend, and updates `agency.json` last. Migration from jj to Git also
|
|
162
|
+
blocks jj-only heads that are not preserved by a bookmark or workspace. Failed
|
|
163
|
+
migrations restore the source repositories and workspaces when rollback is
|
|
164
|
+
possible and report explicit manual recovery paths otherwise.
|
|
165
|
+
|
|
141
166
|
Existing version 2 workbases without `repositories` remain valid. Run
|
|
142
167
|
`agency repo setup` to preview deterministic adoption of legacy local aliases;
|
|
143
168
|
`agency repo setup --apply` writes declarations only when a portable origin is
|
|
@@ -146,7 +171,7 @@ creation command.
|
|
|
146
171
|
|
|
147
172
|
### Custom Worktree Command
|
|
148
173
|
|
|
149
|
-
|
|
174
|
+
Git workbases create worktrees with Git. Set `worktreeCreateCommand` to an
|
|
150
175
|
argv template when another tool should create writable worktrees:
|
|
151
176
|
|
|
152
177
|
```json
|
|
@@ -205,9 +230,10 @@ Custom commands own writable branch creation. Agency checks for conflicting
|
|
|
205
230
|
worktrees first, invokes the command only when the branch is not checked out,
|
|
206
231
|
and verifies that `{worktree}` exists afterward.
|
|
207
232
|
|
|
208
|
-
The configured command applies only to the writable checkout.
|
|
209
|
-
read-only repositories remain detached Git worktrees at their
|
|
210
|
-
they do not acquire writable branches.
|
|
233
|
+
The configured command applies only to the writable checkout of a Git workbase.
|
|
234
|
+
Supplemental read-only repositories remain detached Git worktrees at their
|
|
235
|
+
declared refs so they do not acquire writable branches. Jj workbases always use
|
|
236
|
+
jj workspaces and ignore this Git-specific customization.
|
|
211
237
|
|
|
212
238
|
### Agent Runners
|
|
213
239
|
|
|
@@ -589,6 +615,26 @@ agency task create <id> --multi-phase
|
|
|
589
615
|
[--ticket-url <url>] [--description <text>] [--epic <id>] [--json]
|
|
590
616
|
```
|
|
591
617
|
|
|
618
|
+
Create a pinned, read-only review task from the selected alias's origin:
|
|
619
|
+
|
|
620
|
+
```text
|
|
621
|
+
agency task create <id> --review <alias> --pull-request <url-or-number>
|
|
622
|
+
agency task create <id> --review <alias> --ref <remote-ref>
|
|
623
|
+
agency review refresh <id> [--if-revision <hash>] [--json]
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Review creation fetches the source and records its exact 40-character commit.
|
|
627
|
+
GitHub pull requests use the base alias's `refs/pull/<number>/head`, including
|
|
628
|
+
fork pull requests exposed through that ref. Review workspaces contain one
|
|
629
|
+
detached checkout and no writable branch. Source movement is observed separately
|
|
630
|
+
from the pin and applied only by `review refresh`; sync, doctor, work, cleanup,
|
|
631
|
+
and archive never move the pin implicitly. Dirty or structurally unexpected
|
|
632
|
+
review checkouts block refresh and cleanup. Review tasks support normal status
|
|
633
|
+
and claim lifecycle, but reject phase conversion and delivery PR operations.
|
|
634
|
+
Each active or archived review task owns one internal task-scoped pin ref. A
|
|
635
|
+
refresh advances that ref transactionally; failed creation removes it. Archiving
|
|
636
|
+
retains the pin so a deleted source can still be restored and inspected.
|
|
637
|
+
|
|
592
638
|
### Noninteractive Use
|
|
593
639
|
|
|
594
640
|
Agency never prompts when `--no-input` is set or stdin/stderr are not TTYs.
|
|
@@ -771,7 +817,8 @@ their built-in presets. Launches are interactive and promptless by default; use
|
|
|
771
817
|
`--auto` to send Agency's generated context prompt.
|
|
772
818
|
|
|
773
819
|
`agency work prepare` resolves an execution unit and creates or reuses its
|
|
774
|
-
writable and reference worktrees
|
|
820
|
+
writable and reference worktrees, or its single pinned review checkout, without
|
|
821
|
+
launching an agent or changing status.
|
|
775
822
|
Its JSON result includes document and checkout paths, resolved commits, actions,
|
|
776
823
|
and Git operations. Use `--dry-run` to report planned fetch, branch, and worktree
|
|
777
824
|
changes without applying them.
|
package/cli.ts
CHANGED
|
@@ -43,6 +43,15 @@ import { SyncService } from "./src/services/SyncService"
|
|
|
43
43
|
import { ReadinessService } from "./src/services/ReadinessService"
|
|
44
44
|
import { GraphMutationService } from "./src/services/GraphMutationService"
|
|
45
45
|
import { DoctorService } from "./src/services/DoctorService"
|
|
46
|
+
import { ReviewService } from "./src/services/ReviewService"
|
|
47
|
+
import {
|
|
48
|
+
GitVersionControlService,
|
|
49
|
+
JjVersionControlService,
|
|
50
|
+
VersionControlService,
|
|
51
|
+
} from "./src/services/VersionControlService"
|
|
52
|
+
import { review, help as reviewHelp } from "./src/commands/review"
|
|
53
|
+
import { vcs, help as vcsHelp } from "./src/commands/vcs"
|
|
54
|
+
import { VcsMigrationService } from "./src/services/VcsMigrationService"
|
|
46
55
|
import {
|
|
47
56
|
claimCommand,
|
|
48
57
|
claimHelp,
|
|
@@ -60,6 +69,10 @@ import {
|
|
|
60
69
|
const CliLayer = Layer.mergeAll(
|
|
61
70
|
FileSystemService.Default,
|
|
62
71
|
WorkbaseService.Default,
|
|
72
|
+
GitVersionControlService.Default,
|
|
73
|
+
JjVersionControlService.Default,
|
|
74
|
+
VersionControlService.Default,
|
|
75
|
+
VcsMigrationService.Default,
|
|
63
76
|
RepositoryService.Default,
|
|
64
77
|
EpicService.Default,
|
|
65
78
|
TaskService.Default,
|
|
@@ -75,6 +88,7 @@ const CliLayer = Layer.mergeAll(
|
|
|
75
88
|
ReadinessService.Default,
|
|
76
89
|
GraphMutationService.Default,
|
|
77
90
|
DoctorService.Default,
|
|
91
|
+
ReviewService.Default,
|
|
78
92
|
)
|
|
79
93
|
|
|
80
94
|
/**
|
|
@@ -449,6 +463,9 @@ const commands: Record<string, Command> = {
|
|
|
449
463
|
clearDescription: options["clear-description"],
|
|
450
464
|
epic: options.epic,
|
|
451
465
|
repo: options.repo?.[0],
|
|
466
|
+
review: options.review,
|
|
467
|
+
pullRequest: options["pull-request"],
|
|
468
|
+
ref: options.ref,
|
|
452
469
|
references: options.reference,
|
|
453
470
|
branch: options.branch,
|
|
454
471
|
base: options.base,
|
|
@@ -477,6 +494,22 @@ const commands: Record<string, Command> = {
|
|
|
477
494
|
)
|
|
478
495
|
},
|
|
479
496
|
},
|
|
497
|
+
review: {
|
|
498
|
+
run: async (args: string[], options: Record<string, any>) => {
|
|
499
|
+
if (options.help) return console.log(reviewHelp)
|
|
500
|
+
await runCommand(
|
|
501
|
+
review({
|
|
502
|
+
subcommand: args[0],
|
|
503
|
+
taskId: args[1],
|
|
504
|
+
ifRevision: options["if-revision"],
|
|
505
|
+
json: options.json,
|
|
506
|
+
silent: options.silent,
|
|
507
|
+
verbose: options.verbose,
|
|
508
|
+
cwd: options.cwd,
|
|
509
|
+
}),
|
|
510
|
+
)
|
|
511
|
+
},
|
|
512
|
+
},
|
|
480
513
|
work: {
|
|
481
514
|
run: async (args: string[], options: Record<string, any>) => {
|
|
482
515
|
if (options.help) {
|
|
@@ -525,6 +558,26 @@ const commands: Record<string, Command> = {
|
|
|
525
558
|
)
|
|
526
559
|
},
|
|
527
560
|
},
|
|
561
|
+
vcs: {
|
|
562
|
+
run: async (args: string[], options: Record<string, any>) => {
|
|
563
|
+
if (options.help) {
|
|
564
|
+
console.log(vcsHelp)
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
await runCommand(
|
|
568
|
+
vcs({
|
|
569
|
+
subcommand: args[0],
|
|
570
|
+
target: args[1],
|
|
571
|
+
apply: options.apply,
|
|
572
|
+
dryRun: options["dry-run"],
|
|
573
|
+
json: options.json,
|
|
574
|
+
silent: options.silent,
|
|
575
|
+
verbose: options.verbose,
|
|
576
|
+
cwd: options.cwd,
|
|
577
|
+
}),
|
|
578
|
+
)
|
|
579
|
+
},
|
|
580
|
+
},
|
|
528
581
|
next: {
|
|
529
582
|
run: async (_args: string[], options: Record<string, any>) => {
|
|
530
583
|
if (options.help) return console.log(nextHelp)
|
|
@@ -680,9 +733,11 @@ Commands:
|
|
|
680
733
|
archive <type> Archive a work item
|
|
681
734
|
task <subcommand> Manage tasks
|
|
682
735
|
work [directory|task] Work on an epic, task, or phase
|
|
683
|
-
worktree <subcommand> Inspect and maintain managed
|
|
736
|
+
worktree <subcommand> Inspect and maintain managed workspaces
|
|
737
|
+
vcs <subcommand> Inspect or migrate the version-control backend
|
|
684
738
|
next List or select ready execution units
|
|
685
739
|
pr create Create a pull request for an execution unit
|
|
740
|
+
review refresh Explicitly refresh a pinned review task
|
|
686
741
|
repo <subcommand> Manage workbase repositories
|
|
687
742
|
status Show status for the current workbase
|
|
688
743
|
doctor Diagnose workbase health and integrations
|
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"required": ["version"],
|
|
23
23
|
"properties": {
|
|
24
24
|
"version": { "const": 2 },
|
|
25
|
+
"vcs": { "enum": ["git", "jj"] },
|
|
25
26
|
"root": { "type": "string" }
|
|
26
27
|
}
|
|
27
28
|
},
|
|
@@ -176,6 +177,7 @@
|
|
|
176
177
|
{ "$ref": "#/$defs/epicData" },
|
|
177
178
|
{ "$ref": "#/$defs/singleTaskData" },
|
|
178
179
|
{ "$ref": "#/$defs/multiTaskData" },
|
|
180
|
+
{ "$ref": "#/$defs/reviewTaskData" },
|
|
179
181
|
{ "$ref": "#/$defs/phaseData" },
|
|
180
182
|
{ "$ref": "#/$defs/executionData" },
|
|
181
183
|
{ "$ref": "#/$defs/repositoryData" }
|
|
@@ -220,7 +222,8 @@
|
|
|
220
222
|
"data": {
|
|
221
223
|
"oneOf": [
|
|
222
224
|
{ "$ref": "#/$defs/singleTaskData" },
|
|
223
|
-
{ "$ref": "#/$defs/multiTaskData" }
|
|
225
|
+
{ "$ref": "#/$defs/multiTaskData" },
|
|
226
|
+
{ "$ref": "#/$defs/reviewTaskData" }
|
|
224
227
|
]
|
|
225
228
|
},
|
|
226
229
|
"workspace": { "$ref": "#/$defs/documentWorkspace" },
|
|
@@ -358,34 +361,72 @@
|
|
|
358
361
|
"sha256": { "type": "string" }
|
|
359
362
|
}
|
|
360
363
|
},
|
|
361
|
-
"
|
|
364
|
+
"reviewSource": {
|
|
365
|
+
"oneOf": [
|
|
366
|
+
{
|
|
367
|
+
"type": "object",
|
|
368
|
+
"additionalProperties": false,
|
|
369
|
+
"required": [
|
|
370
|
+
"kind",
|
|
371
|
+
"provider",
|
|
372
|
+
"repository",
|
|
373
|
+
"identifier",
|
|
374
|
+
"url",
|
|
375
|
+
"fetchRef"
|
|
376
|
+
],
|
|
377
|
+
"properties": {
|
|
378
|
+
"kind": { "const": "pull-request" },
|
|
379
|
+
"provider": { "const": "github" },
|
|
380
|
+
"repository": { "type": "string" },
|
|
381
|
+
"identifier": { "type": "string", "pattern": "^\\d+$" },
|
|
382
|
+
"url": {
|
|
383
|
+
"type": "string",
|
|
384
|
+
"pattern": "^https://github\\.com/[^/]+/[^/]+/pull/\\d+$"
|
|
385
|
+
},
|
|
386
|
+
"fetchRef": { "type": "string", "pattern": "^refs/pull/\\d+/head$" }
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"type": "object",
|
|
391
|
+
"additionalProperties": false,
|
|
392
|
+
"required": ["kind", "ref"],
|
|
393
|
+
"properties": {
|
|
394
|
+
"kind": { "const": "branch" },
|
|
395
|
+
"ref": { "type": "string", "pattern": "^refs/heads/" }
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
},
|
|
400
|
+
"reviewRecord": {
|
|
362
401
|
"type": "object",
|
|
363
402
|
"additionalProperties": false,
|
|
364
|
-
"required": ["repo", "
|
|
403
|
+
"required": ["repo", "source", "commit", "refreshedAt"],
|
|
365
404
|
"properties": {
|
|
366
|
-
"description": { "type": "string" },
|
|
367
405
|
"repo": { "type": "string" },
|
|
368
|
-
"
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
406
|
+
"source": { "$ref": "#/$defs/reviewSource" },
|
|
407
|
+
"commit": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
|
|
408
|
+
"refreshedAt": { "type": "string", "format": "date-time" }
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
"reviewTaskData": {
|
|
412
|
+
"type": "object",
|
|
413
|
+
"additionalProperties": false,
|
|
414
|
+
"required": ["ticketUrl", "review", "status", "sha256"],
|
|
415
|
+
"properties": {
|
|
416
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
417
|
+
"description": { "type": "string" },
|
|
418
|
+
"epic": { "type": "string" },
|
|
419
|
+
"review": { "$ref": "#/$defs/reviewRecord" },
|
|
375
420
|
"status": { "$ref": "#/$defs/status" },
|
|
376
421
|
"claim": { "$ref": "#/$defs/claim" },
|
|
377
422
|
"sha256": { "type": "string" }
|
|
378
423
|
}
|
|
379
424
|
},
|
|
380
|
-
"
|
|
425
|
+
"phaseData": {
|
|
381
426
|
"type": "object",
|
|
382
427
|
"additionalProperties": false,
|
|
383
|
-
"required": ["
|
|
428
|
+
"required": ["repo", "branch", "base", "pr", "status", "sha256"],
|
|
384
429
|
"properties": {
|
|
385
|
-
"taskId": { "type": "string" },
|
|
386
|
-
"phaseId": { "type": "string" },
|
|
387
|
-
"ticketUrl": { "type": ["string", "null"] },
|
|
388
|
-
"epic": { "type": "string" },
|
|
389
430
|
"description": { "type": "string" },
|
|
390
431
|
"repo": { "type": "string" },
|
|
391
432
|
"repos": {
|
|
@@ -396,9 +437,50 @@
|
|
|
396
437
|
"base": { "type": "string" },
|
|
397
438
|
"pr": { "type": ["string", "null"] },
|
|
398
439
|
"status": { "$ref": "#/$defs/status" },
|
|
399
|
-
"claim": { "$ref": "#/$defs/claim" }
|
|
440
|
+
"claim": { "$ref": "#/$defs/claim" },
|
|
441
|
+
"sha256": { "type": "string" }
|
|
400
442
|
}
|
|
401
443
|
},
|
|
444
|
+
"executionData": {
|
|
445
|
+
"oneOf": [
|
|
446
|
+
{
|
|
447
|
+
"type": "object",
|
|
448
|
+
"additionalProperties": false,
|
|
449
|
+
"required": ["taskId", "repo", "branch", "base", "pr", "status"],
|
|
450
|
+
"properties": {
|
|
451
|
+
"taskId": { "type": "string" },
|
|
452
|
+
"phaseId": { "type": "string" },
|
|
453
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
454
|
+
"epic": { "type": "string" },
|
|
455
|
+
"description": { "type": "string" },
|
|
456
|
+
"repo": { "type": "string" },
|
|
457
|
+
"repos": {
|
|
458
|
+
"type": "array",
|
|
459
|
+
"items": { "$ref": "#/$defs/repositoryReference" }
|
|
460
|
+
},
|
|
461
|
+
"branch": { "type": "string" },
|
|
462
|
+
"base": { "type": "string" },
|
|
463
|
+
"pr": { "type": ["string", "null"] },
|
|
464
|
+
"status": { "$ref": "#/$defs/status" },
|
|
465
|
+
"claim": { "$ref": "#/$defs/claim" }
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
"type": "object",
|
|
470
|
+
"additionalProperties": false,
|
|
471
|
+
"required": ["taskId", "ticketUrl", "review", "status"],
|
|
472
|
+
"properties": {
|
|
473
|
+
"taskId": { "type": "string" },
|
|
474
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
475
|
+
"description": { "type": "string" },
|
|
476
|
+
"epic": { "type": "string" },
|
|
477
|
+
"review": { "$ref": "#/$defs/reviewRecord" },
|
|
478
|
+
"status": { "$ref": "#/$defs/status" },
|
|
479
|
+
"claim": { "$ref": "#/$defs/claim" }
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
]
|
|
483
|
+
},
|
|
402
484
|
"claim": {
|
|
403
485
|
"type": "object",
|
|
404
486
|
"additionalProperties": false,
|
|
@@ -469,26 +551,48 @@
|
|
|
469
551
|
}
|
|
470
552
|
},
|
|
471
553
|
"executionGit": {
|
|
472
|
-
"
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
554
|
+
"oneOf": [
|
|
555
|
+
{
|
|
556
|
+
"type": "object",
|
|
557
|
+
"additionalProperties": false,
|
|
558
|
+
"required": [
|
|
559
|
+
"branch",
|
|
560
|
+
"base",
|
|
561
|
+
"branchCommit",
|
|
562
|
+
"baseCommit",
|
|
563
|
+
"checkoutCommit",
|
|
564
|
+
"checkoutBranch",
|
|
565
|
+
"dirty"
|
|
566
|
+
],
|
|
567
|
+
"properties": {
|
|
568
|
+
"branch": { "type": "string" },
|
|
569
|
+
"base": { "type": "string" },
|
|
570
|
+
"branchCommit": { "type": ["string", "null"] },
|
|
571
|
+
"baseCommit": { "type": ["string", "null"] },
|
|
572
|
+
"checkoutCommit": { "type": ["string", "null"] },
|
|
573
|
+
"checkoutBranch": { "type": ["string", "null"] },
|
|
574
|
+
"dirty": { "type": ["boolean", "null"] }
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"type": "object",
|
|
579
|
+
"additionalProperties": false,
|
|
580
|
+
"required": [
|
|
581
|
+
"pinnedCommit",
|
|
582
|
+
"sourceCommit",
|
|
583
|
+
"checkoutCommit",
|
|
584
|
+
"checkoutBranch",
|
|
585
|
+
"dirty"
|
|
586
|
+
],
|
|
587
|
+
"properties": {
|
|
588
|
+
"pinnedCommit": { "type": "string" },
|
|
589
|
+
"sourceCommit": { "type": ["string", "null"] },
|
|
590
|
+
"checkoutCommit": { "type": ["string", "null"] },
|
|
591
|
+
"checkoutBranch": { "type": ["string", "null"] },
|
|
592
|
+
"dirty": { "type": ["boolean", "null"] }
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
]
|
|
492
596
|
},
|
|
493
597
|
"pr": {
|
|
494
598
|
"oneOf": [
|
package/src/cli-parser.test.ts
CHANGED
|
@@ -7,6 +7,68 @@ const expectUsageError = (args: string[], usage: string) => {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
describe("strict CLI parsing", () => {
|
|
10
|
+
test("accepts review creation and refresh while enforcing one source", () => {
|
|
11
|
+
expect(
|
|
12
|
+
parseCli([
|
|
13
|
+
"task",
|
|
14
|
+
"create",
|
|
15
|
+
"review-it",
|
|
16
|
+
"--review",
|
|
17
|
+
"agency",
|
|
18
|
+
"--pull-request",
|
|
19
|
+
"42",
|
|
20
|
+
]).values,
|
|
21
|
+
).toMatchObject({ review: "agency", "pull-request": "42" })
|
|
22
|
+
expect(() =>
|
|
23
|
+
parseCli([
|
|
24
|
+
"task",
|
|
25
|
+
"create",
|
|
26
|
+
"review-it",
|
|
27
|
+
"--review",
|
|
28
|
+
"agency",
|
|
29
|
+
"--ref",
|
|
30
|
+
"feature/review",
|
|
31
|
+
]),
|
|
32
|
+
).not.toThrow()
|
|
33
|
+
expect(() =>
|
|
34
|
+
parseCli([
|
|
35
|
+
"review",
|
|
36
|
+
"refresh",
|
|
37
|
+
"review-it",
|
|
38
|
+
"--if-revision",
|
|
39
|
+
"a".repeat(64),
|
|
40
|
+
]),
|
|
41
|
+
).not.toThrow()
|
|
42
|
+
expect(() =>
|
|
43
|
+
parseCli([
|
|
44
|
+
"task",
|
|
45
|
+
"create",
|
|
46
|
+
"review-it",
|
|
47
|
+
"--review",
|
|
48
|
+
"agency",
|
|
49
|
+
"--pull-request",
|
|
50
|
+
"42",
|
|
51
|
+
"--ref",
|
|
52
|
+
"feature/review",
|
|
53
|
+
]),
|
|
54
|
+
).toThrow("exactly one")
|
|
55
|
+
for (const extra of [
|
|
56
|
+
["--ref", "feature/review", "--repo", "agency"],
|
|
57
|
+
["--ref", "feature/review", "--multi-phase"],
|
|
58
|
+
]) {
|
|
59
|
+
expect(() =>
|
|
60
|
+
parseCli([
|
|
61
|
+
"task",
|
|
62
|
+
"create",
|
|
63
|
+
"review-it",
|
|
64
|
+
"--review",
|
|
65
|
+
"agency",
|
|
66
|
+
...extra,
|
|
67
|
+
]),
|
|
68
|
+
).toThrow("cannot be combined")
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
10
72
|
test("accepts every documented orchestration recipe command", () => {
|
|
11
73
|
for (const args of orchestrationRecipes) {
|
|
12
74
|
expect(() => parseCli(args)).not.toThrow()
|
|
@@ -509,6 +571,25 @@ describe("strict CLI parsing", () => {
|
|
|
509
571
|
)
|
|
510
572
|
})
|
|
511
573
|
|
|
574
|
+
test("parses VCS status and migration commands", () => {
|
|
575
|
+
expect(parseCli(["vcs", "status", "--json"])).toMatchObject({
|
|
576
|
+
commandName: "vcs",
|
|
577
|
+
args: ["status"],
|
|
578
|
+
values: { json: true },
|
|
579
|
+
})
|
|
580
|
+
expect(
|
|
581
|
+
parseCli(["vcs", "migrate", "jj", "--apply", "--json"]),
|
|
582
|
+
).toMatchObject({
|
|
583
|
+
commandName: "vcs",
|
|
584
|
+
args: ["migrate", "jj"],
|
|
585
|
+
values: { apply: true, json: true },
|
|
586
|
+
})
|
|
587
|
+
expectUsageError(["vcs", "migrate"], "agency vcs migrate")
|
|
588
|
+
expect(() =>
|
|
589
|
+
parseCli(["vcs", "migrate", "jj", "--dry-run", "--apply"]),
|
|
590
|
+
).toThrow("cannot be combined")
|
|
591
|
+
})
|
|
592
|
+
|
|
512
593
|
test("accepts runner selection and command inspection for work", () => {
|
|
513
594
|
expect(
|
|
514
595
|
parseCli([
|