@markjaquith/agency 2.73.2 → 3.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 +35 -134
- package/cli-main.ts +0 -26
- package/cli.ts +1 -17
- package/package.json +1 -2
- package/schemas/agency-graph-v1.schema.json +1 -1
- package/src/cli-parser.test.ts +0 -19
- package/src/cli-parser.ts +0 -23
- package/src/cli.test.ts +3 -3
- package/src/commands/context.test.ts +11 -71
- package/src/commands/context.ts +7 -7
- package/src/commands/init.test.ts +1 -2
- package/src/commands/pr.test.ts +2 -87
- package/src/commands/pr.ts +2 -79
- package/src/commands/push.test.ts +1 -2
- package/src/graph-schema.ts +1 -1
- package/src/services/ArchiveBulkService.test.ts +1 -142
- package/src/services/ArchiveService.test.ts +1 -172
- package/src/services/ArchiveService.ts +0 -26
- package/src/services/ContextService.ts +7 -50
- package/src/services/DoctorService.ts +8 -24
- package/src/services/GraphService.test.ts +1 -0
- package/src/services/GraphService.ts +2 -5
- package/src/services/IntegrationService.test.ts +4 -0
- package/src/services/PhaseService.ts +70 -191
- package/src/services/PullRequestService.test.ts +1 -45
- package/src/services/PullRequestService.ts +1 -22
- package/src/services/PushService.test.ts +29 -295
- package/src/services/PushService.ts +10 -239
- package/src/services/RepositoryService.test.ts +1 -61
- package/src/services/RepositoryService.ts +2 -13
- package/src/services/ReviewService.test.ts +1 -84
- package/src/services/ReviewService.ts +9 -48
- package/src/services/SyncService.test.ts +0 -81
- package/src/services/SyncService.ts +12 -39
- package/src/services/TaskPhaseService.test.ts +0 -80
- package/src/services/TaskService.ts +1 -9
- package/src/services/VersionControlService.test.ts +4 -117
- package/src/services/VersionControlService.ts +3 -426
- package/src/services/WorkbaseService.test.ts +0 -20
- package/src/services/WorkbaseService.ts +1 -18
- package/src/services/WorktreeService.test.ts +1 -705
- package/src/services/WorktreeService.ts +395 -1604
- package/src/services/push-validation.ts +0 -7
- package/src/test-utils.ts +0 -4
- package/src/workbase/AGENTS.md +7 -7
- package/src/workbase/checkout-command.test.ts +1 -1
- package/src/workbase/checkout-command.ts +1 -1
- package/src/workbase/delivery-command.test.ts +4 -35
- package/src/workbase/delivery-command.ts +2 -15
- package/src/workbase/schemas.test.ts +0 -19
- package/src/workbase/schemas.ts +1 -2
- package/src/commands/vcs.test.ts +0 -75
- package/src/commands/vcs.ts +0 -72
- package/src/services/VcsMigrationService.test.ts +0 -348
- package/src/services/VcsMigrationService.ts +0 -857
- package/src/vcs-status-fast.ts +0 -310
- package/src/workbase/version-control.ts +0 -5
- package/src/workbase/workspace-command.test.ts +0 -70
- package/src/workbase/workspace-command.ts +0 -63
package/README.md
CHANGED
|
@@ -9,7 +9,6 @@ read or write.
|
|
|
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
|
|
13
12
|
- [GitHub CLI](https://cli.github.com/) for `agency pr`
|
|
14
13
|
- OpenCode, Claude Code, or a configured agent for `agency work`
|
|
15
14
|
|
|
@@ -151,15 +150,16 @@ the writable checkout's `.claude/skills`, `.agents/skills`,
|
|
|
151
150
|
`.opencode/{skill,skills}`, and `.pi/skills` directories. `agency context`
|
|
152
151
|
remains the authority for writes; reference checkouts remain read-only.
|
|
153
152
|
|
|
154
|
-
Repository aliases
|
|
155
|
-
|
|
156
|
-
`repos/{alias}`. A declaration contains no local path, symlink target,
|
|
157
|
-
or credential
|
|
153
|
+
Repository aliases and canonical fetch remotes are declared in tracked
|
|
154
|
+
`agency.json`; local Git clones and symlinks remain ignored under
|
|
155
|
+
`repos/{alias}`. A declaration contains no local path, symlink target, worktree,
|
|
156
|
+
or credential. The optional `vcs` field accepts only `"git"`; omitting it also
|
|
157
|
+
selects Git:
|
|
158
158
|
|
|
159
159
|
```json
|
|
160
160
|
{
|
|
161
161
|
"version": 2,
|
|
162
|
-
"vcs": "
|
|
162
|
+
"vcs": "git",
|
|
163
163
|
"repositories": {
|
|
164
164
|
"frontend": {
|
|
165
165
|
"remote": "git@example.com:team/frontend.git"
|
|
@@ -168,39 +168,9 @@ or credential:
|
|
|
168
168
|
}
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
non-colocated managed clones and jj workspaces, while Git workbases continue to
|
|
175
|
-
use bare repositories and Git worktrees. Existing colocated jj repositories are
|
|
176
|
-
also supported.
|
|
177
|
-
|
|
178
|
-
Agency uses jj-native commands for repository validity, workspace registration,
|
|
179
|
-
working-copy state, revisions, bookmarks, ancestry, fetch, and push. Raw Git is
|
|
180
|
-
limited to backing-store plumbing such as durable review refs and integrations
|
|
181
|
-
that require Git, including GitHub CLI commit discovery. For those operations,
|
|
182
|
-
Agency obtains the backing repository with `jj git root` and supplies it as
|
|
183
|
-
`GIT_DIR`; it does not use raw Git to infer jj workspace state.
|
|
184
|
-
|
|
185
|
-
Inspect the current backend and migration readiness with:
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
agency vcs status
|
|
189
|
-
agency vcs migrate jj # dry-run
|
|
190
|
-
agency vcs migrate jj --apply
|
|
191
|
-
agency vcs migrate git --apply
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Migration is workbase-wide and transactional. Agency locks every execution
|
|
195
|
-
unit, requires clean registered workspaces, blocks active claims and working or
|
|
196
|
-
delegated units, converts repository metadata, recreates checkout paths with the
|
|
197
|
-
target backend, and updates `agency.json` last. Migration from jj to Git also
|
|
198
|
-
blocks jj-only heads that are not preserved by a bookmark or workspace. Failed
|
|
199
|
-
migrations restore the source repositories and workspaces when rollback is
|
|
200
|
-
possible and report explicit manual recovery paths otherwise.
|
|
201
|
-
Converting a non-colocated jj workbase to Git is currently blocked before any
|
|
202
|
-
mutation because its backing Git object store is inside `.jj`; first convert the
|
|
203
|
-
repositories to colocated jj so the Git store survives metadata removal.
|
|
171
|
+
Agency materializes declared remotes as bare Git repositories and creates
|
|
172
|
+
managed Git worktrees for execution units. Linked aliases remain symlinks to
|
|
173
|
+
existing Git repositories.
|
|
204
174
|
|
|
205
175
|
Existing version 2 workbases without `repositories` remain valid. Run
|
|
206
176
|
`agency repo setup` to preview deterministic adoption of legacy local aliases;
|
|
@@ -274,63 +244,13 @@ Agency also reconciles known tool-owned artifacts such as Worktrunk's
|
|
|
274
244
|
new and existing managed worktrees clean without changing the repository's
|
|
275
245
|
tracked ignore configuration or overwriting user-maintained local excludes.
|
|
276
246
|
|
|
277
|
-
The configured command applies only to the writable checkout
|
|
247
|
+
The configured command applies only to the writable checkout.
|
|
278
248
|
Supplemental read-only repositories remain detached Git worktrees at their
|
|
279
|
-
declared refs so they do not acquire writable branches.
|
|
280
|
-
jj workspaces and ignore this Git-specific customization.
|
|
281
|
-
|
|
282
|
-
### Custom Jj Workspace Command
|
|
283
|
-
|
|
284
|
-
Jj workbases normally create managed workspaces with `jj workspace add`. Set
|
|
285
|
-
`workspaceCreateCommand` to an argv template when another tool should create or
|
|
286
|
-
adopt a prepared workspace directly at Agency's destination:
|
|
287
|
-
|
|
288
|
-
```json
|
|
289
|
-
{
|
|
290
|
-
"version": 2,
|
|
291
|
-
"vcs": "jj",
|
|
292
|
-
"workspaceCreateCommand": [
|
|
293
|
-
"my-prewarm-tool",
|
|
294
|
-
"adopt",
|
|
295
|
-
"--repo",
|
|
296
|
-
"{repo}",
|
|
297
|
-
"--destination",
|
|
298
|
-
"{workspace}",
|
|
299
|
-
"--name",
|
|
300
|
-
"{name}",
|
|
301
|
-
"--revision",
|
|
302
|
-
"{revision}"
|
|
303
|
-
]
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
Available placeholders are:
|
|
308
|
-
|
|
309
|
-
- `{repo}`: absolute repository alias path under `repos/`
|
|
310
|
-
- `{workspace}`: absolute managed workspace path Agency requires
|
|
311
|
-
- `{name}`: unique jj workspace name Agency requires
|
|
312
|
-
- `{revision}`: exact commit the new working copy must be based on
|
|
313
|
-
- `{kind}`: `writable` or `reference`
|
|
314
|
-
- `{requestedRef}`: configured branch, reference, or review commit
|
|
315
|
-
|
|
316
|
-
`{repo}`, `{workspace}`, `{name}`, and `{revision}` are required. Agency invokes
|
|
317
|
-
the command directly without a shell and sets matching `AGENCY_REPO`,
|
|
318
|
-
`AGENCY_WORKSPACE`, `AGENCY_WORKSPACE_NAME`, `AGENCY_REVISION`,
|
|
319
|
-
`AGENCY_CHECKOUT_KIND`, and `AGENCY_REQUESTED_REF` environment variables. The
|
|
320
|
-
command applies to each new jj checkout and must leave `{workspace}` registered
|
|
321
|
-
under `{name}` with its working-copy parent at `{revision}`. This lets a prewarm
|
|
322
|
-
tool move or adopt a prepared workspace without first paying for Agency's normal
|
|
323
|
-
full checkout.
|
|
324
|
-
|
|
325
|
-
Agency validates the registration, name, path, and revision before running any
|
|
326
|
-
`postCheckoutCommand`. A failed command or validation removes a partially
|
|
327
|
-
created workspace when possible and otherwise reports manual recovery. Resume
|
|
328
|
-
restoration continues to use Agency's built-in exact-target recovery path.
|
|
329
|
-
Git workbases ignore this jj-specific customization.
|
|
249
|
+
declared refs so they do not acquire writable branches.
|
|
330
250
|
|
|
331
251
|
### Post-checkout Commands
|
|
332
252
|
|
|
333
|
-
Each repository declaration may provide a
|
|
253
|
+
Each repository declaration may provide a `postCheckoutCommand` argv
|
|
334
254
|
template for repository-specific setup. Agency invokes it directly, without a
|
|
335
255
|
shell, with the new checkout as its working directory:
|
|
336
256
|
|
|
@@ -346,11 +266,10 @@ shell, with the new checkout as its working directory:
|
|
|
346
266
|
}
|
|
347
267
|
```
|
|
348
268
|
|
|
349
|
-
The hook runs for each newly created managed
|
|
350
|
-
reference
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
`workspaceCreateCommand` completes and is validated before this hook runs.
|
|
269
|
+
The hook runs for each newly created managed Git worktree, including writable
|
|
270
|
+
and reference worktrees, after Agency has validated it. It does not run for a
|
|
271
|
+
reused worktree or for inspection-only commands. A custom
|
|
272
|
+
`worktreeCreateCommand` completes and is validated before this hook runs.
|
|
354
273
|
|
|
355
274
|
Available placeholders and matching environment variables are:
|
|
356
275
|
|
|
@@ -362,7 +281,7 @@ Available placeholders and matching environment variables are:
|
|
|
362
281
|
| `{checkoutKind}` | `AGENCY_CHECKOUT_KIND` | `writable` or `reference` |
|
|
363
282
|
| `{requestedRef}` | `AGENCY_REQUESTED_REF` | Requested branch, reference, or review commit |
|
|
364
283
|
| `{base}` | `AGENCY_BASE` | Configured execution base |
|
|
365
|
-
| `{vcs}` | `AGENCY_VCS` | `git`
|
|
284
|
+
| `{vcs}` | `AGENCY_VCS` | `git` |
|
|
366
285
|
| `{workbaseRoot}` | `AGENCY_WORKBASE_ROOT` | Absolute workbase root |
|
|
367
286
|
| `{taskId}` | `AGENCY_TASK_ID` | Task ID |
|
|
368
287
|
| `{phaseId}` | `AGENCY_PHASE_ID` | Phase ID |
|
|
@@ -631,7 +550,7 @@ included in generated or executed pull request commands.
|
|
|
631
550
|
|
|
632
551
|
### Target Context
|
|
633
552
|
|
|
634
|
-
`agency context [target] --json` returns
|
|
553
|
+
`agency context [target] --json` returns compact bootstrap context without
|
|
635
554
|
modifying the workbase or fetching repositories. At the workbase root it returns
|
|
636
555
|
a discovery catalog of all epics, tasks, and phases, including frontmatter,
|
|
637
556
|
paths, and document revisions. Elsewhere it returns context for an epic, task,
|
|
@@ -642,15 +561,15 @@ explicitly marked with `target.archived: true` and never grants writable
|
|
|
642
561
|
document, repository checkout, or reference authority; restore the item before
|
|
643
562
|
attempting mutation or execution.
|
|
644
563
|
|
|
645
|
-
Root discovery
|
|
646
|
-
. --full --json` when document prose is needed.
|
|
647
|
-
|
|
564
|
+
Root discovery and entity context are compact by default. Root discovery includes
|
|
565
|
+
a hint to run `agency context . --full --json` when document prose is needed.
|
|
566
|
+
`--compact` remains available as an explicit request for the compact projection.
|
|
648
567
|
|
|
649
|
-
The result includes workbase and target identity, ancestor frontmatter
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
568
|
+
The result includes workbase and target identity, ancestor frontmatter with
|
|
569
|
+
SHA-256 hashes, dependency and readiness state, aggregate status, writable and
|
|
570
|
+
reference authority, local materialization state, recorded PR state, and
|
|
571
|
+
validation warnings. Only `done` satisfies a dependency; `dropped` is terminal
|
|
572
|
+
but remains a blocker.
|
|
654
573
|
|
|
655
574
|
`authority.writable` identifies the writable repository checkout, while
|
|
656
575
|
`authority.documents.writable` lists the absolute paths of Agency documents the
|
|
@@ -658,10 +577,9 @@ target may maintain. A single-phase task lists its `TASK.md`; a phase lists its
|
|
|
658
577
|
owning `TASK.md` and active `PHASE.md`; orchestration targets list none. Use
|
|
659
578
|
Agency commands rather than direct edits for structural frontmatter mutations.
|
|
660
579
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
warnings.
|
|
580
|
+
Pass `--full` to include document prose and low-level VCS details. Compact output
|
|
581
|
+
retains identity, hashes, authority, paths, graph state, materialization state,
|
|
582
|
+
recorded PR state, and validation warnings.
|
|
665
583
|
|
|
666
584
|
### Workbase Graph
|
|
667
585
|
|
|
@@ -1163,15 +1081,6 @@ conflicting worktrees. Repair is deliberately conservative: it repairs safe Git
|
|
|
1163
1081
|
registration issues and materializes missing checkouts, but never switches a
|
|
1164
1082
|
branch, resets a commit, or discards uncommitted work.
|
|
1165
1083
|
|
|
1166
|
-
For jj, explicit removal is a suspend operation. Agency records each workspace's
|
|
1167
|
-
exact `@` commit and stable change ID in `.agency-jj-resume.json`, roots that
|
|
1168
|
-
commit with an internal local bookmark, and only then forgets the workspace.
|
|
1169
|
-
The next `work prepare` validates all three identities, restores the workspace by
|
|
1170
|
-
editing the recorded commit, and consumes the resume metadata and bookmarks.
|
|
1171
|
-
Missing, ambiguous, or conflicting resume state stops instead of falling back to
|
|
1172
|
-
the declared delivery bookmark, `@-`, or the base. Unknown checkout cleanliness
|
|
1173
|
-
also stops removal. Git worktree removal and preparation are unchanged.
|
|
1174
|
-
|
|
1175
1084
|
Agency launches every agent beside its epic or task document. Single-phase tasks
|
|
1176
1085
|
and phases first fetch repositories and create or reuse worktrees under `code/`,
|
|
1177
1086
|
then launch the execution agent from the task directory with absolute context
|
|
@@ -1196,18 +1105,11 @@ that the declared base is in the publication history, validates every outgoing
|
|
|
1196
1105
|
commit's description, author, and conflict state, and refuses non-fast-forward
|
|
1197
1106
|
updates.
|
|
1198
1107
|
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
changes remain intentional publication tips. Missing descriptions or authors
|
|
1205
|
-
stop with exact change IDs and remediation commands. Agency creates or safely
|
|
1206
|
-
advances only the declared bookmark and never invents a `push-*` bookmark.
|
|
1207
|
-
If the fetched remote base advanced outside the local stack, Agency prints the
|
|
1208
|
-
exact `jj rebase` command needed to move the stack onto `<base>@<remote>`. Push
|
|
1209
|
-
reports deterministic fetch, inspection, validation, and publication progress
|
|
1210
|
-
on stderr, including while `--json` reserves stdout for one machine result.
|
|
1108
|
+
YAML `branch` must exactly match the checked-out local branch, the worktree must
|
|
1109
|
+
be clean, and `HEAD` is pushed with upstream tracking. Missing commit descriptions
|
|
1110
|
+
or authors stop publication with exact commits and remediation commands. Push
|
|
1111
|
+
reports deterministic fetch, inspection, validation, and publication progress on
|
|
1112
|
+
stderr, including while `--json` reserves stdout for one machine result.
|
|
1211
1113
|
|
|
1212
1114
|
Task-aware `agency pr create <task-id> [phase-id]` uses Agency's delivery flow,
|
|
1213
1115
|
including readiness checks and durable PR recording. It accepts draft, title,
|
|
@@ -1217,8 +1119,7 @@ Other `agency pr`
|
|
|
1217
1119
|
invocations forward every argument to `gh pr`. From an execution task or phase
|
|
1218
1120
|
directory, including descendants, passthrough runs in that execution unit's
|
|
1219
1121
|
authoritative writable checkout. Otherwise it runs in the caller's current
|
|
1220
|
-
directory.
|
|
1221
|
-
item's declared branch to subcommands that would otherwise infer Git context.
|
|
1122
|
+
directory.
|
|
1222
1123
|
|
|
1223
1124
|
### Status and Validation
|
|
1224
1125
|
|
package/cli-main.ts
CHANGED
|
@@ -48,12 +48,9 @@ import { DoctorService } from "./src/services/DoctorService"
|
|
|
48
48
|
import { ReviewService } from "./src/services/ReviewService"
|
|
49
49
|
import {
|
|
50
50
|
GitVersionControlService,
|
|
51
|
-
JjVersionControlService,
|
|
52
51
|
VersionControlService,
|
|
53
52
|
} from "./src/services/VersionControlService"
|
|
54
53
|
import { review, help as reviewHelp } from "./src/commands/review"
|
|
55
|
-
import { vcs, help as vcsHelp } from "./src/commands/vcs"
|
|
56
|
-
import { VcsMigrationService } from "./src/services/VcsMigrationService"
|
|
57
54
|
import { act, help as actHelp } from "./src/commands/act"
|
|
58
55
|
import {
|
|
59
56
|
claimCommand,
|
|
@@ -74,9 +71,7 @@ const CliLayer = Layer.mergeAll(
|
|
|
74
71
|
FileSystemService.Default,
|
|
75
72
|
WorkbaseService.Default,
|
|
76
73
|
GitVersionControlService.Default,
|
|
77
|
-
JjVersionControlService.Default,
|
|
78
74
|
VersionControlService.Default,
|
|
79
|
-
VcsMigrationService.Default,
|
|
80
75
|
RepositoryService.Default,
|
|
81
76
|
EpicService.Default,
|
|
82
77
|
TaskService.Default,
|
|
@@ -623,26 +618,6 @@ const commands: Record<string, Command> = {
|
|
|
623
618
|
)
|
|
624
619
|
},
|
|
625
620
|
},
|
|
626
|
-
vcs: {
|
|
627
|
-
run: async (args: string[], options: Record<string, any>) => {
|
|
628
|
-
if (options.help) {
|
|
629
|
-
console.log(vcsHelp)
|
|
630
|
-
return
|
|
631
|
-
}
|
|
632
|
-
await runCommand(
|
|
633
|
-
vcs({
|
|
634
|
-
subcommand: args[0],
|
|
635
|
-
target: args[1],
|
|
636
|
-
apply: options.apply,
|
|
637
|
-
dryRun: options["dry-run"],
|
|
638
|
-
json: options.json,
|
|
639
|
-
silent: options.silent,
|
|
640
|
-
verbose: options.verbose,
|
|
641
|
-
cwd: options.cwd,
|
|
642
|
-
}),
|
|
643
|
-
)
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
621
|
next: {
|
|
647
622
|
run: async (_args: string[], options: Record<string, any>) => {
|
|
648
623
|
if (options.help) return console.log(nextHelp)
|
|
@@ -802,7 +777,6 @@ Commands:
|
|
|
802
777
|
task <subcommand> Manage tasks
|
|
803
778
|
work [directory|task] Work on an epic, task, or phase
|
|
804
779
|
worktree <subcommand> Inspect and maintain managed workspaces
|
|
805
|
-
vcs <subcommand> Inspect or migrate the version-control backend
|
|
806
780
|
next List or select ready execution units
|
|
807
781
|
pr create / pr [...] Create an Agency PR or run gh pr with repository focus
|
|
808
782
|
push Validate and publish the current execution unit
|
package/cli.ts
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const fastVcsStatus =
|
|
5
|
-
args[0] === "vcs" &&
|
|
6
|
-
args[1] === "status" &&
|
|
7
|
-
(args.length === 2 || (args.length === 3 && args[2] === "--json"))
|
|
8
|
-
|
|
9
|
-
if (fastVcsStatus) {
|
|
10
|
-
try {
|
|
11
|
-
const { runVcsStatusFast } = await import("./src/vcs-status-fast")
|
|
12
|
-
if (!(await runVcsStatusFast(args[2] === "--json")))
|
|
13
|
-
await import("./cli-main")
|
|
14
|
-
} catch {
|
|
15
|
-
await import("./cli-main")
|
|
16
|
-
}
|
|
17
|
-
} else {
|
|
18
|
-
await import("./cli-main")
|
|
19
|
-
}
|
|
3
|
+
await import("./cli-main")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markjaquith/agency",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Manage agentic work across repositories with durable workbases",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -83,7 +83,6 @@
|
|
|
83
83
|
"benchmark:graph": "bun scripts/benchmark-graph.ts",
|
|
84
84
|
"benchmark:push": "bun scripts/benchmark-push.ts",
|
|
85
85
|
"benchmark:archive": "bun scripts/benchmark-archive.ts",
|
|
86
|
-
"benchmark:vcs": "bun scripts/benchmark-vcs.ts",
|
|
87
86
|
"benchmark:sync": "bun scripts/benchmark-sync.ts",
|
|
88
87
|
"benchmark:task": "bun scripts/benchmark-task.ts",
|
|
89
88
|
"benchmark:validate": "bun scripts/benchmark-validate.ts",
|
package/src/cli-parser.test.ts
CHANGED
|
@@ -674,25 +674,6 @@ describe("strict CLI parsing", () => {
|
|
|
674
674
|
)
|
|
675
675
|
})
|
|
676
676
|
|
|
677
|
-
test("parses VCS status and migration commands", () => {
|
|
678
|
-
expect(parseCli(["vcs", "status", "--json"])).toMatchObject({
|
|
679
|
-
commandName: "vcs",
|
|
680
|
-
args: ["status"],
|
|
681
|
-
values: { json: true },
|
|
682
|
-
})
|
|
683
|
-
expect(
|
|
684
|
-
parseCli(["vcs", "migrate", "jj", "--apply", "--json"]),
|
|
685
|
-
).toMatchObject({
|
|
686
|
-
commandName: "vcs",
|
|
687
|
-
args: ["migrate", "jj"],
|
|
688
|
-
values: { apply: true, json: true },
|
|
689
|
-
})
|
|
690
|
-
expectUsageError(["vcs", "migrate"], "agency vcs migrate")
|
|
691
|
-
expect(() =>
|
|
692
|
-
parseCli(["vcs", "migrate", "jj", "--dry-run", "--apply"]),
|
|
693
|
-
).toThrow("cannot be combined")
|
|
694
|
-
})
|
|
695
|
-
|
|
696
677
|
test("parses push without accepting an alternate target", () => {
|
|
697
678
|
expect(parseCli(["push", "--json"])).toMatchObject({
|
|
698
679
|
commandName: "push",
|
package/src/cli-parser.ts
CHANGED
|
@@ -908,29 +908,6 @@ const commands = {
|
|
|
908
908
|
},
|
|
909
909
|
},
|
|
910
910
|
},
|
|
911
|
-
vcs: {
|
|
912
|
-
usage: "agency vcs <status|migrate>",
|
|
913
|
-
options: {
|
|
914
|
-
...outputOptions,
|
|
915
|
-
apply: { type: "boolean" },
|
|
916
|
-
"dry-run": { type: "boolean" },
|
|
917
|
-
},
|
|
918
|
-
subcommands: {
|
|
919
|
-
status: {
|
|
920
|
-
usage: "agency vcs status [--json]",
|
|
921
|
-
minArgs: 0,
|
|
922
|
-
maxArgs: 0,
|
|
923
|
-
options: ["json"],
|
|
924
|
-
},
|
|
925
|
-
migrate: {
|
|
926
|
-
usage: "agency vcs migrate <git|jj> [--dry-run | --apply] [--json]",
|
|
927
|
-
minArgs: 1,
|
|
928
|
-
maxArgs: 1,
|
|
929
|
-
options: ["apply", "dry-run", "json"],
|
|
930
|
-
conflicts: [["apply", "dry-run"]],
|
|
931
|
-
},
|
|
932
|
-
},
|
|
933
|
-
},
|
|
934
911
|
work: {
|
|
935
912
|
usage:
|
|
936
913
|
"agency work [<directory-or-task-id> | --epic <epic-id>] [--agent <name>] [--auto] | agency work prepare [target] [--dry-run] [--json]",
|
package/src/cli.test.ts
CHANGED
|
@@ -1929,9 +1929,9 @@ status: open
|
|
|
1929
1929
|
alias: "agency",
|
|
1930
1930
|
status: "applied",
|
|
1931
1931
|
})
|
|
1932
|
-
expect(
|
|
1933
|
-
|
|
1934
|
-
)
|
|
1932
|
+
expect((await stat(join(restored, "repos/agency/HEAD"))).isFile()).toBe(
|
|
1933
|
+
true,
|
|
1934
|
+
)
|
|
1935
1935
|
|
|
1936
1936
|
const prepared = parseJson(
|
|
1937
1937
|
await runCli(["work", "prepare", "portable", "--json"], restored),
|
|
@@ -161,9 +161,9 @@ Phase prose.
|
|
|
161
161
|
await cleanupTempDir(root)
|
|
162
162
|
})
|
|
163
163
|
|
|
164
|
-
test("returns
|
|
164
|
+
test("returns full phase context with graph, authority, Git, and validation state", async () => {
|
|
165
165
|
const target = "tasks/agent-contract/phases/context-command"
|
|
166
|
-
const result = await readContext(root, target)
|
|
166
|
+
const result = await readContext(root, target, false, true)
|
|
167
167
|
|
|
168
168
|
expect(result).toMatchObject({
|
|
169
169
|
projection: "complete",
|
|
@@ -219,81 +219,19 @@ Phase prose.
|
|
|
219
219
|
)
|
|
220
220
|
})
|
|
221
221
|
|
|
222
|
-
test("
|
|
223
|
-
|
|
224
|
-
await cleanupTempDir(root)
|
|
225
|
-
root = await createTempDir()
|
|
226
|
-
const remote = join(root, "remote.git")
|
|
227
|
-
const seed = join(root, "seed")
|
|
228
|
-
const repository = join(root, "repos/agency")
|
|
229
|
-
const checkout = join(root, "tasks/example/code/agency")
|
|
230
|
-
await mkdir(join(root, "repos"), { recursive: true })
|
|
231
|
-
await write(root, "agency.json", '{"version":2,"vcs":"jj"}\n')
|
|
232
|
-
await run(root, ["git", "init", "--bare", "--initial-branch=main", remote])
|
|
233
|
-
await run(root, ["git", "init", "--initial-branch=main", seed])
|
|
234
|
-
await run(seed, ["git", "config", "user.email", "test@example.com"])
|
|
235
|
-
await run(seed, ["git", "config", "user.name", "Test"])
|
|
236
|
-
await Bun.write(join(seed, "README.md"), "example\n")
|
|
237
|
-
await run(seed, ["git", "add", "README.md"])
|
|
238
|
-
await run(seed, ["git", "commit", "-m", "initial"])
|
|
239
|
-
await run(seed, ["git", "remote", "add", "origin", remote])
|
|
240
|
-
await run(seed, ["git", "push", "origin", "main"])
|
|
241
|
-
await run(root, ["jj", "git", "clone", "--no-colocate", remote, repository])
|
|
242
|
-
await write(
|
|
222
|
+
test("defaults to compact while preserving explicit compact compatibility", async () => {
|
|
223
|
+
const result = await readContext(
|
|
243
224
|
root,
|
|
244
|
-
"tasks/
|
|
245
|
-
`---
|
|
246
|
-
ticketUrl: null
|
|
247
|
-
repo: agency
|
|
248
|
-
branch: task/example
|
|
249
|
-
base: main
|
|
250
|
-
pr: null
|
|
251
|
-
status: working
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
# Example
|
|
255
|
-
`,
|
|
256
|
-
)
|
|
257
|
-
await mkdir(dirname(checkout), { recursive: true })
|
|
258
|
-
await run(repository, [
|
|
259
|
-
"jj",
|
|
260
|
-
"workspace",
|
|
261
|
-
"add",
|
|
262
|
-
"--name",
|
|
263
|
-
"task-example",
|
|
264
|
-
"-r",
|
|
265
|
-
"main",
|
|
266
|
-
checkout,
|
|
267
|
-
])
|
|
268
|
-
await Bun.write(join(checkout, "feature.txt"), "current change\n")
|
|
269
|
-
const current = Bun.spawn(
|
|
270
|
-
["jj", "log", "--no-graph", "-r", "@", "-T", "commit_id"],
|
|
271
|
-
{ cwd: checkout, stdout: "pipe", stderr: "pipe" },
|
|
272
|
-
)
|
|
273
|
-
const currentCommit = (await new Response(current.stdout).text()).trim()
|
|
274
|
-
expect(await current.exited).toBe(0)
|
|
275
|
-
|
|
276
|
-
const result = await readContext(root, "tasks/example")
|
|
277
|
-
expect(result.workspace.writable).toMatchObject({
|
|
278
|
-
branchCommit: null,
|
|
279
|
-
checkoutCommit: currentCommit,
|
|
280
|
-
checkoutBranch: null,
|
|
281
|
-
detached: true,
|
|
282
|
-
dirty: false,
|
|
283
|
-
})
|
|
284
|
-
expect(result.workspace.warnings).toContain(
|
|
285
|
-
`Unable to resolve branch 'task/example' in ${repository}`,
|
|
225
|
+
"tasks/agent-contract/phases/context-command/code/agency",
|
|
286
226
|
)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
test("makes compact projection explicit without omitting essential identity", async () => {
|
|
290
|
-
const result = await readContext(
|
|
227
|
+
const explicit = await readContext(
|
|
291
228
|
root,
|
|
292
229
|
"tasks/agent-contract/phases/context-command/code/agency",
|
|
293
230
|
true,
|
|
294
231
|
)
|
|
295
232
|
|
|
296
233
|
expect(result.projection).toBe("compact")
|
|
234
|
+
expect(explicit).toEqual(result)
|
|
297
235
|
expect(result.target.kind).toBe("phase")
|
|
298
236
|
expect(result.documents.phase.body).toBeUndefined()
|
|
299
237
|
expect(result.documents.phase.data.branch).toBe("feat/context")
|
|
@@ -441,7 +379,7 @@ status: dropped
|
|
|
441
379
|
join(root, "archive/tasks/foundations"),
|
|
442
380
|
)
|
|
443
381
|
|
|
444
|
-
const result = await readContext(root, "foundations")
|
|
382
|
+
const result = await readContext(root, "foundations", false, true)
|
|
445
383
|
|
|
446
384
|
expect(result.target).toMatchObject({
|
|
447
385
|
kind: "task",
|
|
@@ -488,6 +426,8 @@ status: dropped
|
|
|
488
426
|
const result = await readContext(
|
|
489
427
|
root,
|
|
490
428
|
"archive/tasks/agent-contract/phases/context-command",
|
|
429
|
+
false,
|
|
430
|
+
true,
|
|
491
431
|
)
|
|
492
432
|
|
|
493
433
|
expect(result.target).toMatchObject({
|
|
@@ -529,7 +469,7 @@ status: dropped
|
|
|
529
469
|
)
|
|
530
470
|
}
|
|
531
471
|
|
|
532
|
-
const result = await readContext(root, "epics/contract")
|
|
472
|
+
const result = await readContext(root, "epics/contract", false, true)
|
|
533
473
|
|
|
534
474
|
expect(result.target).toMatchObject({
|
|
535
475
|
kind: "epic",
|
package/src/commands/context.ts
CHANGED
|
@@ -21,16 +21,16 @@ export const context = (options: ContextOptions = {}) =>
|
|
|
21
21
|
export const help = `
|
|
22
22
|
Usage: agency context [target] [options]
|
|
23
23
|
|
|
24
|
-
Return
|
|
25
|
-
target defaults to the current directory and may be the workbase
|
|
26
|
-
path, or a task ID. Archived entities are inspectable but never
|
|
27
|
-
or execution authority. Workbase context catalogs all active
|
|
28
|
-
phases.
|
|
24
|
+
Return read-only context for a workbase, epic, task, or phase. Compact output is
|
|
25
|
+
the default. The target defaults to the current directory and may be the workbase
|
|
26
|
+
root, an entity path, or a task ID. Archived entities are inspectable but never
|
|
27
|
+
receive mutation or execution authority. Workbase context catalogs all active
|
|
28
|
+
epics, tasks, and phases.
|
|
29
29
|
|
|
30
30
|
Options:
|
|
31
31
|
--json Output a versioned machine result
|
|
32
|
-
--compact
|
|
33
|
-
--full Include prose bodies
|
|
32
|
+
--compact Use compact output (default)
|
|
33
|
+
--full Include prose bodies and low-level VCS details
|
|
34
34
|
--epic <id> Select an epic
|
|
35
35
|
--task <id> Select a task
|
|
36
36
|
--phase <id> Select a phase together with --task
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
runTestEffect,
|
|
9
9
|
} from "../test-utils"
|
|
10
10
|
import { init } from "./init"
|
|
11
|
-
import { preferredVersionControl } from "../workbase/version-control"
|
|
12
11
|
|
|
13
12
|
describe("init command", () => {
|
|
14
13
|
let parent: string
|
|
@@ -27,7 +26,7 @@ describe("init command", () => {
|
|
|
27
26
|
|
|
28
27
|
expect(await Bun.file(join(root, "agency.json")).json()).toEqual({
|
|
29
28
|
version: 2,
|
|
30
|
-
vcs:
|
|
29
|
+
vcs: "git",
|
|
31
30
|
})
|
|
32
31
|
for (const directory of ["repos", "epics", "tasks"]) {
|
|
33
32
|
expect((await stat(join(root, directory))).isDirectory()).toBe(true)
|