@markjaquith/agency 2.48.1 → 2.50.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 +40 -9
- package/cli.ts +32 -0
- package/package.json +1 -1
- package/schemas/agency-graph-v1.schema.json +141 -38
- package/src/cli-parser.test.ts +120 -0
- package/src/cli-parser.ts +122 -7
- package/src/cli.test.ts +71 -0
- package/src/commands/claim.ts +26 -2
- package/src/commands/phase.ts +23 -2
- package/src/commands/review.ts +38 -0
- package/src/commands/task.ts +49 -7
- package/src/commands/work.test.ts +2 -0
- package/src/commands/work.ts +2 -2
- package/src/graph-schema.ts +35 -13
- package/src/protocol.ts +1 -0
- package/src/services/ArchiveService.test.ts +2 -2
- package/src/services/ArchiveService.ts +1 -0
- package/src/services/ClaimService.test.ts +59 -0
- package/src/services/ClaimService.ts +36 -2
- package/src/services/ContextService.ts +56 -4
- package/src/services/DoctorService.ts +45 -1
- package/src/services/GraphMutationService.ts +21 -0
- package/src/services/GraphService.ts +118 -54
- package/src/services/IntegrationService.test.ts +4 -1
- package/src/services/PhaseService.ts +55 -3
- package/src/services/PullRequestService.test.ts +22 -2
- package/src/services/PullRequestService.ts +44 -3
- package/src/services/ReadinessService.ts +7 -3
- package/src/services/ReviewService.test.ts +472 -0
- package/src/services/ReviewService.ts +404 -0
- package/src/services/SyncService.test.ts +68 -2
- package/src/services/SyncService.ts +123 -6
- package/src/services/TaskPhaseService.test.ts +182 -0
- package/src/services/TaskService.ts +128 -11
- package/src/services/WorkbaseService.test.ts +58 -0
- package/src/services/WorkbaseService.ts +22 -1
- package/src/services/WorktreeService.test.ts +16 -16
- package/src/services/WorktreeService.ts +76 -40
- package/src/test-utils.ts +2 -0
- package/src/work-view.ts +14 -6
- package/src/workbase/AGENTS.md +7 -2
- package/src/workbase/completion.ts +28 -0
- package/src/workbase/schemas.test.ts +57 -0
- package/src/workbase/schemas.ts +65 -0
package/README.md
CHANGED
|
@@ -589,6 +589,26 @@ agency task create <id> --multi-phase
|
|
|
589
589
|
[--ticket-url <url>] [--description <text>] [--epic <id>] [--json]
|
|
590
590
|
```
|
|
591
591
|
|
|
592
|
+
Create a pinned, read-only review task from the selected alias's origin:
|
|
593
|
+
|
|
594
|
+
```text
|
|
595
|
+
agency task create <id> --review <alias> --pull-request <url-or-number>
|
|
596
|
+
agency task create <id> --review <alias> --ref <remote-ref>
|
|
597
|
+
agency review refresh <id> [--if-revision <hash>] [--json]
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
Review creation fetches the source and records its exact 40-character commit.
|
|
601
|
+
GitHub pull requests use the base alias's `refs/pull/<number>/head`, including
|
|
602
|
+
fork pull requests exposed through that ref. Review workspaces contain one
|
|
603
|
+
detached checkout and no writable branch. Source movement is observed separately
|
|
604
|
+
from the pin and applied only by `review refresh`; sync, doctor, work, cleanup,
|
|
605
|
+
and archive never move the pin implicitly. Dirty or structurally unexpected
|
|
606
|
+
review checkouts block refresh and cleanup. Review tasks support normal status
|
|
607
|
+
and claim lifecycle, but reject phase conversion and delivery PR operations.
|
|
608
|
+
Each active or archived review task owns one internal task-scoped pin ref. A
|
|
609
|
+
refresh advances that ref transactionally; failed creation removes it. Archiving
|
|
610
|
+
retains the pin so a deleted source can still be restored and inspected.
|
|
611
|
+
|
|
592
612
|
### Noninteractive Use
|
|
593
613
|
|
|
594
614
|
Agency never prompts when `--no-input` is set or stdin/stderr are not TTYs.
|
|
@@ -610,7 +630,8 @@ Inspect tasks:
|
|
|
610
630
|
```text
|
|
611
631
|
agency task list [filters] [--json]
|
|
612
632
|
agency task show <id> [--json]
|
|
613
|
-
agency task status <id> <open|working|dropped>
|
|
633
|
+
agency task status <id> <open|working|done|dropped>
|
|
634
|
+
[--no-pull-request --summary <text> [--evidence-url <url>]] [--json]
|
|
614
635
|
agency task update <id> [metadata options] [--json]
|
|
615
636
|
agency task rename <id> <new-id> [--json]
|
|
616
637
|
agency task move <id> (--epic <epic-id> | --no-epic) [--json]
|
|
@@ -649,7 +670,8 @@ agency phase create <task-id> <phase-id>
|
|
|
649
670
|
|
|
650
671
|
agency phase list <task-id> [filters] [--json]
|
|
651
672
|
agency phase show <task-id> <phase-id> [--json]
|
|
652
|
-
agency phase status <task-id> <phase-id> <open|working|dropped>
|
|
673
|
+
agency phase status <task-id> <phase-id> <open|working|done|dropped>
|
|
674
|
+
[--no-pull-request --summary <text> [--evidence-url <url>]] [--json]
|
|
653
675
|
agency phase update <task-id> <phase-id> [metadata options] [--json]
|
|
654
676
|
agency phase rename <task-id> <phase-id> <new-id> [--json]
|
|
655
677
|
agency phase dependency <add|remove> <task-id> <phase-id> <dependency-id>
|
|
@@ -672,8 +694,12 @@ writing anything.
|
|
|
672
694
|
Single-phase tasks and phases store status in YAML. New execution units start
|
|
673
695
|
`open`, and `agency work` marks the selected execution unit `working` immediately
|
|
674
696
|
before launch. Running `agency work` again can relaunch unclaimed `working` work.
|
|
675
|
-
|
|
676
|
-
|
|
697
|
+
By default, `done` requires an authoritative merged pull request and is applied
|
|
698
|
+
by `agency sync --apply`. Work whose intended outcome genuinely requires no pull
|
|
699
|
+
request may instead use an explicit `--no-pull-request --summary <text>` status
|
|
700
|
+
transition. Agency records the summary, completion time, and optional evidence
|
|
701
|
+
URL durably; reopening removes that evidence. This exceptional path refuses work
|
|
702
|
+
that already has a recorded pull request.
|
|
677
703
|
Use explicit claims only when an external orchestrator needs coordinated
|
|
678
704
|
ownership. The interactive work selector displays status markers before
|
|
679
705
|
execution units. Existing working and delegated work may be released to `open`
|
|
@@ -704,15 +730,19 @@ agency claim <task-id> [phase-id] --claimant <id> --runner <id>
|
|
|
704
730
|
agency release <task-id> [phase-id] --session-id <id>
|
|
705
731
|
--revision <sha256> [--json]
|
|
706
732
|
agency finish <task-id> [phase-id] --session-id <id>
|
|
707
|
-
--revision <sha256> --outcome <done|dropped>
|
|
733
|
+
--revision <sha256> --outcome <done|dropped>
|
|
734
|
+
[--no-pull-request --summary <text> [--evidence-url <url>]] [--json]
|
|
708
735
|
```
|
|
709
736
|
|
|
710
737
|
An active claim sets status to `working`. Release returns it to `open`. Finish
|
|
711
738
|
records the claim outcome and ownership history; a `done` claim outcome leaves
|
|
712
739
|
the execution unit `working` until its pull request is merged, while `dropped`
|
|
713
|
-
remains terminal.
|
|
714
|
-
|
|
715
|
-
|
|
740
|
+
remains terminal. For a genuine non-PR outcome, `--no-pull-request` atomically
|
|
741
|
+
records completion evidence, finishes the claim, and sets the execution unit to
|
|
742
|
+
`done`; `--summary` is required and `--evidence-url` is optional. Conflicts return
|
|
743
|
+
the current revision and complete ownership record in the machine error envelope
|
|
744
|
+
rather than overwriting it. Expired claims may be replaced with a
|
|
745
|
+
revision-guarded claim.
|
|
716
746
|
|
|
717
747
|
`agency work` does not claim execution units. It refuses active explicit claims,
|
|
718
748
|
marks open execution work `working`, and launches the runner. External
|
|
@@ -761,7 +791,8 @@ their built-in presets. Launches are interactive and promptless by default; use
|
|
|
761
791
|
`--auto` to send Agency's generated context prompt.
|
|
762
792
|
|
|
763
793
|
`agency work prepare` resolves an execution unit and creates or reuses its
|
|
764
|
-
writable and reference worktrees
|
|
794
|
+
writable and reference worktrees, or its single pinned review checkout, without
|
|
795
|
+
launching an agent or changing status.
|
|
765
796
|
Its JSON result includes document and checkout paths, resolved commits, actions,
|
|
766
797
|
and Git operations. Use `--dry-run` to report planned fetch, branch, and worktree
|
|
767
798
|
changes without applying them.
|
package/cli.ts
CHANGED
|
@@ -43,6 +43,8 @@ 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 { review, help as reviewHelp } from "./src/commands/review"
|
|
46
48
|
import {
|
|
47
49
|
claimCommand,
|
|
48
50
|
claimHelp,
|
|
@@ -75,6 +77,7 @@ const CliLayer = Layer.mergeAll(
|
|
|
75
77
|
ReadinessService.Default,
|
|
76
78
|
GraphMutationService.Default,
|
|
77
79
|
DoctorService.Default,
|
|
80
|
+
ReviewService.Default,
|
|
78
81
|
)
|
|
79
82
|
|
|
80
83
|
/**
|
|
@@ -205,6 +208,9 @@ const commands: Record<string, Command> = {
|
|
|
205
208
|
sessionId: options["session-id"],
|
|
206
209
|
revision: options.revision,
|
|
207
210
|
outcome: options.outcome,
|
|
211
|
+
noPullRequest: options["no-pull-request"],
|
|
212
|
+
summary: options.summary,
|
|
213
|
+
evidenceUrl: options["evidence-url"],
|
|
208
214
|
json: options.json,
|
|
209
215
|
silent: options.silent,
|
|
210
216
|
verbose: options.verbose,
|
|
@@ -298,6 +304,9 @@ const commands: Record<string, Command> = {
|
|
|
298
304
|
clearReferences: options["clear-references"],
|
|
299
305
|
prUrl: options["pr-url"],
|
|
300
306
|
clearPr: options["clear-pr"],
|
|
307
|
+
noPullRequest: options["no-pull-request"],
|
|
308
|
+
summary: options.summary,
|
|
309
|
+
evidenceUrl: options["evidence-url"],
|
|
301
310
|
ifRevision: options["if-revision"],
|
|
302
311
|
dependsOn: options["depends-on"],
|
|
303
312
|
firstPhase: options["first-phase"],
|
|
@@ -443,12 +452,18 @@ const commands: Record<string, Command> = {
|
|
|
443
452
|
clearDescription: options["clear-description"],
|
|
444
453
|
epic: options.epic,
|
|
445
454
|
repo: options.repo?.[0],
|
|
455
|
+
review: options.review,
|
|
456
|
+
pullRequest: options["pull-request"],
|
|
457
|
+
ref: options.ref,
|
|
446
458
|
references: options.reference,
|
|
447
459
|
branch: options.branch,
|
|
448
460
|
base: options.base,
|
|
449
461
|
clearReferences: options["clear-references"],
|
|
450
462
|
prUrl: options["pr-url"],
|
|
451
463
|
clearPr: options["clear-pr"],
|
|
464
|
+
noPullRequest: options["no-pull-request"],
|
|
465
|
+
summary: options.summary,
|
|
466
|
+
evidenceUrl: options["evidence-url"],
|
|
452
467
|
ifRevision: options["if-revision"],
|
|
453
468
|
noEpic: options["no-epic"],
|
|
454
469
|
multiPhase: options["multi-phase"],
|
|
@@ -468,6 +483,22 @@ const commands: Record<string, Command> = {
|
|
|
468
483
|
)
|
|
469
484
|
},
|
|
470
485
|
},
|
|
486
|
+
review: {
|
|
487
|
+
run: async (args: string[], options: Record<string, any>) => {
|
|
488
|
+
if (options.help) return console.log(reviewHelp)
|
|
489
|
+
await runCommand(
|
|
490
|
+
review({
|
|
491
|
+
subcommand: args[0],
|
|
492
|
+
taskId: args[1],
|
|
493
|
+
ifRevision: options["if-revision"],
|
|
494
|
+
json: options.json,
|
|
495
|
+
silent: options.silent,
|
|
496
|
+
verbose: options.verbose,
|
|
497
|
+
cwd: options.cwd,
|
|
498
|
+
}),
|
|
499
|
+
)
|
|
500
|
+
},
|
|
501
|
+
},
|
|
471
502
|
work: {
|
|
472
503
|
run: async (args: string[], options: Record<string, any>) => {
|
|
473
504
|
if (options.help) {
|
|
@@ -674,6 +705,7 @@ Commands:
|
|
|
674
705
|
worktree <subcommand> Inspect and maintain managed worktrees
|
|
675
706
|
next List or select ready execution units
|
|
676
707
|
pr create Create a pull request for an execution unit
|
|
708
|
+
review refresh Explicitly refresh a pinned review task
|
|
677
709
|
repo <subcommand> Manage workbase repositories
|
|
678
710
|
status Show status for the current workbase
|
|
679
711
|
doctor Diagnose workbase health and integrations
|
package/package.json
CHANGED
|
@@ -176,6 +176,7 @@
|
|
|
176
176
|
{ "$ref": "#/$defs/epicData" },
|
|
177
177
|
{ "$ref": "#/$defs/singleTaskData" },
|
|
178
178
|
{ "$ref": "#/$defs/multiTaskData" },
|
|
179
|
+
{ "$ref": "#/$defs/reviewTaskData" },
|
|
179
180
|
{ "$ref": "#/$defs/phaseData" },
|
|
180
181
|
{ "$ref": "#/$defs/executionData" },
|
|
181
182
|
{ "$ref": "#/$defs/repositoryData" }
|
|
@@ -220,7 +221,8 @@
|
|
|
220
221
|
"data": {
|
|
221
222
|
"oneOf": [
|
|
222
223
|
{ "$ref": "#/$defs/singleTaskData" },
|
|
223
|
-
{ "$ref": "#/$defs/multiTaskData" }
|
|
224
|
+
{ "$ref": "#/$defs/multiTaskData" },
|
|
225
|
+
{ "$ref": "#/$defs/reviewTaskData" }
|
|
224
226
|
]
|
|
225
227
|
},
|
|
226
228
|
"workspace": { "$ref": "#/$defs/documentWorkspace" },
|
|
@@ -358,34 +360,72 @@
|
|
|
358
360
|
"sha256": { "type": "string" }
|
|
359
361
|
}
|
|
360
362
|
},
|
|
361
|
-
"
|
|
363
|
+
"reviewSource": {
|
|
364
|
+
"oneOf": [
|
|
365
|
+
{
|
|
366
|
+
"type": "object",
|
|
367
|
+
"additionalProperties": false,
|
|
368
|
+
"required": [
|
|
369
|
+
"kind",
|
|
370
|
+
"provider",
|
|
371
|
+
"repository",
|
|
372
|
+
"identifier",
|
|
373
|
+
"url",
|
|
374
|
+
"fetchRef"
|
|
375
|
+
],
|
|
376
|
+
"properties": {
|
|
377
|
+
"kind": { "const": "pull-request" },
|
|
378
|
+
"provider": { "const": "github" },
|
|
379
|
+
"repository": { "type": "string" },
|
|
380
|
+
"identifier": { "type": "string", "pattern": "^\\d+$" },
|
|
381
|
+
"url": {
|
|
382
|
+
"type": "string",
|
|
383
|
+
"pattern": "^https://github\\.com/[^/]+/[^/]+/pull/\\d+$"
|
|
384
|
+
},
|
|
385
|
+
"fetchRef": { "type": "string", "pattern": "^refs/pull/\\d+/head$" }
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"type": "object",
|
|
390
|
+
"additionalProperties": false,
|
|
391
|
+
"required": ["kind", "ref"],
|
|
392
|
+
"properties": {
|
|
393
|
+
"kind": { "const": "branch" },
|
|
394
|
+
"ref": { "type": "string", "pattern": "^refs/heads/" }
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
},
|
|
399
|
+
"reviewRecord": {
|
|
362
400
|
"type": "object",
|
|
363
401
|
"additionalProperties": false,
|
|
364
|
-
"required": ["repo", "
|
|
402
|
+
"required": ["repo", "source", "commit", "refreshedAt"],
|
|
365
403
|
"properties": {
|
|
366
|
-
"description": { "type": "string" },
|
|
367
404
|
"repo": { "type": "string" },
|
|
368
|
-
"
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
405
|
+
"source": { "$ref": "#/$defs/reviewSource" },
|
|
406
|
+
"commit": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
|
|
407
|
+
"refreshedAt": { "type": "string", "format": "date-time" }
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
"reviewTaskData": {
|
|
411
|
+
"type": "object",
|
|
412
|
+
"additionalProperties": false,
|
|
413
|
+
"required": ["ticketUrl", "review", "status", "sha256"],
|
|
414
|
+
"properties": {
|
|
415
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
416
|
+
"description": { "type": "string" },
|
|
417
|
+
"epic": { "type": "string" },
|
|
418
|
+
"review": { "$ref": "#/$defs/reviewRecord" },
|
|
375
419
|
"status": { "$ref": "#/$defs/status" },
|
|
376
420
|
"claim": { "$ref": "#/$defs/claim" },
|
|
377
421
|
"sha256": { "type": "string" }
|
|
378
422
|
}
|
|
379
423
|
},
|
|
380
|
-
"
|
|
424
|
+
"phaseData": {
|
|
381
425
|
"type": "object",
|
|
382
426
|
"additionalProperties": false,
|
|
383
|
-
"required": ["
|
|
427
|
+
"required": ["repo", "branch", "base", "pr", "status", "sha256"],
|
|
384
428
|
"properties": {
|
|
385
|
-
"taskId": { "type": "string" },
|
|
386
|
-
"phaseId": { "type": "string" },
|
|
387
|
-
"ticketUrl": { "type": ["string", "null"] },
|
|
388
|
-
"epic": { "type": "string" },
|
|
389
429
|
"description": { "type": "string" },
|
|
390
430
|
"repo": { "type": "string" },
|
|
391
431
|
"repos": {
|
|
@@ -396,9 +436,50 @@
|
|
|
396
436
|
"base": { "type": "string" },
|
|
397
437
|
"pr": { "type": ["string", "null"] },
|
|
398
438
|
"status": { "$ref": "#/$defs/status" },
|
|
399
|
-
"claim": { "$ref": "#/$defs/claim" }
|
|
439
|
+
"claim": { "$ref": "#/$defs/claim" },
|
|
440
|
+
"sha256": { "type": "string" }
|
|
400
441
|
}
|
|
401
442
|
},
|
|
443
|
+
"executionData": {
|
|
444
|
+
"oneOf": [
|
|
445
|
+
{
|
|
446
|
+
"type": "object",
|
|
447
|
+
"additionalProperties": false,
|
|
448
|
+
"required": ["taskId", "repo", "branch", "base", "pr", "status"],
|
|
449
|
+
"properties": {
|
|
450
|
+
"taskId": { "type": "string" },
|
|
451
|
+
"phaseId": { "type": "string" },
|
|
452
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
453
|
+
"epic": { "type": "string" },
|
|
454
|
+
"description": { "type": "string" },
|
|
455
|
+
"repo": { "type": "string" },
|
|
456
|
+
"repos": {
|
|
457
|
+
"type": "array",
|
|
458
|
+
"items": { "$ref": "#/$defs/repositoryReference" }
|
|
459
|
+
},
|
|
460
|
+
"branch": { "type": "string" },
|
|
461
|
+
"base": { "type": "string" },
|
|
462
|
+
"pr": { "type": ["string", "null"] },
|
|
463
|
+
"status": { "$ref": "#/$defs/status" },
|
|
464
|
+
"claim": { "$ref": "#/$defs/claim" }
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"type": "object",
|
|
469
|
+
"additionalProperties": false,
|
|
470
|
+
"required": ["taskId", "ticketUrl", "review", "status"],
|
|
471
|
+
"properties": {
|
|
472
|
+
"taskId": { "type": "string" },
|
|
473
|
+
"ticketUrl": { "type": ["string", "null"] },
|
|
474
|
+
"description": { "type": "string" },
|
|
475
|
+
"epic": { "type": "string" },
|
|
476
|
+
"review": { "$ref": "#/$defs/reviewRecord" },
|
|
477
|
+
"status": { "$ref": "#/$defs/status" },
|
|
478
|
+
"claim": { "$ref": "#/$defs/claim" }
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
]
|
|
482
|
+
},
|
|
402
483
|
"claim": {
|
|
403
484
|
"type": "object",
|
|
404
485
|
"additionalProperties": false,
|
|
@@ -469,26 +550,48 @@
|
|
|
469
550
|
}
|
|
470
551
|
},
|
|
471
552
|
"executionGit": {
|
|
472
|
-
"
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
553
|
+
"oneOf": [
|
|
554
|
+
{
|
|
555
|
+
"type": "object",
|
|
556
|
+
"additionalProperties": false,
|
|
557
|
+
"required": [
|
|
558
|
+
"branch",
|
|
559
|
+
"base",
|
|
560
|
+
"branchCommit",
|
|
561
|
+
"baseCommit",
|
|
562
|
+
"checkoutCommit",
|
|
563
|
+
"checkoutBranch",
|
|
564
|
+
"dirty"
|
|
565
|
+
],
|
|
566
|
+
"properties": {
|
|
567
|
+
"branch": { "type": "string" },
|
|
568
|
+
"base": { "type": "string" },
|
|
569
|
+
"branchCommit": { "type": ["string", "null"] },
|
|
570
|
+
"baseCommit": { "type": ["string", "null"] },
|
|
571
|
+
"checkoutCommit": { "type": ["string", "null"] },
|
|
572
|
+
"checkoutBranch": { "type": ["string", "null"] },
|
|
573
|
+
"dirty": { "type": ["boolean", "null"] }
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
"type": "object",
|
|
578
|
+
"additionalProperties": false,
|
|
579
|
+
"required": [
|
|
580
|
+
"pinnedCommit",
|
|
581
|
+
"sourceCommit",
|
|
582
|
+
"checkoutCommit",
|
|
583
|
+
"checkoutBranch",
|
|
584
|
+
"dirty"
|
|
585
|
+
],
|
|
586
|
+
"properties": {
|
|
587
|
+
"pinnedCommit": { "type": "string" },
|
|
588
|
+
"sourceCommit": { "type": ["string", "null"] },
|
|
589
|
+
"checkoutCommit": { "type": ["string", "null"] },
|
|
590
|
+
"checkoutBranch": { "type": ["string", "null"] },
|
|
591
|
+
"dirty": { "type": ["boolean", "null"] }
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
]
|
|
492
595
|
},
|
|
493
596
|
"pr": {
|
|
494
597
|
"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()
|
|
@@ -362,6 +424,64 @@ describe("strict CLI parsing", () => {
|
|
|
362
424
|
"working",
|
|
363
425
|
]),
|
|
364
426
|
).toThrow("must be 'done' or 'dropped'")
|
|
427
|
+
expect(
|
|
428
|
+
parseCli([
|
|
429
|
+
"finish",
|
|
430
|
+
"task",
|
|
431
|
+
"--session-id",
|
|
432
|
+
"job-1",
|
|
433
|
+
"--revision",
|
|
434
|
+
revision,
|
|
435
|
+
"--outcome",
|
|
436
|
+
"done",
|
|
437
|
+
"--no-pull-request",
|
|
438
|
+
"--summary",
|
|
439
|
+
"Investigation completed",
|
|
440
|
+
"--evidence-url",
|
|
441
|
+
"https://example.com/result",
|
|
442
|
+
]),
|
|
443
|
+
).toMatchObject({
|
|
444
|
+
values: {
|
|
445
|
+
"no-pull-request": true,
|
|
446
|
+
summary: "Investigation completed",
|
|
447
|
+
"evidence-url": "https://example.com/result",
|
|
448
|
+
},
|
|
449
|
+
})
|
|
450
|
+
expect(() =>
|
|
451
|
+
parseCli([
|
|
452
|
+
"finish",
|
|
453
|
+
"task",
|
|
454
|
+
"--session-id",
|
|
455
|
+
"job-1",
|
|
456
|
+
"--revision",
|
|
457
|
+
revision,
|
|
458
|
+
"--outcome",
|
|
459
|
+
"done",
|
|
460
|
+
"--no-pull-request",
|
|
461
|
+
]),
|
|
462
|
+
).toThrow("--summary' is required")
|
|
463
|
+
expect(() =>
|
|
464
|
+
parseCli([
|
|
465
|
+
"task",
|
|
466
|
+
"status",
|
|
467
|
+
"example",
|
|
468
|
+
"working",
|
|
469
|
+
"--no-pull-request",
|
|
470
|
+
"--summary",
|
|
471
|
+
"Not done",
|
|
472
|
+
]),
|
|
473
|
+
).toThrow("valid only with a done status")
|
|
474
|
+
expect(() =>
|
|
475
|
+
parseCli([
|
|
476
|
+
"phase",
|
|
477
|
+
"status",
|
|
478
|
+
"task",
|
|
479
|
+
"phase",
|
|
480
|
+
"done",
|
|
481
|
+
"--summary",
|
|
482
|
+
"Missing explicit flag",
|
|
483
|
+
]),
|
|
484
|
+
).toThrow("require '--no-pull-request'")
|
|
365
485
|
})
|
|
366
486
|
|
|
367
487
|
test("accepts valid mutation revisions and rejects malformed hashes", () => {
|