@markjaquith/agency 2.74.0 → 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.
Files changed (57) hide show
  1. package/README.md +23 -121
  2. package/cli-main.ts +0 -26
  3. package/cli.ts +1 -17
  4. package/package.json +1 -2
  5. package/schemas/agency-graph-v1.schema.json +1 -1
  6. package/src/cli-parser.test.ts +0 -19
  7. package/src/cli-parser.ts +0 -23
  8. package/src/cli.test.ts +3 -3
  9. package/src/commands/context.test.ts +0 -67
  10. package/src/commands/init.test.ts +1 -2
  11. package/src/commands/pr.test.ts +2 -87
  12. package/src/commands/pr.ts +2 -79
  13. package/src/commands/push.test.ts +1 -2
  14. package/src/graph-schema.ts +1 -1
  15. package/src/services/ArchiveBulkService.test.ts +1 -142
  16. package/src/services/ArchiveService.test.ts +1 -172
  17. package/src/services/ArchiveService.ts +0 -26
  18. package/src/services/ContextService.ts +3 -47
  19. package/src/services/DoctorService.ts +8 -24
  20. package/src/services/GraphService.test.ts +1 -0
  21. package/src/services/GraphService.ts +2 -5
  22. package/src/services/PhaseService.ts +70 -191
  23. package/src/services/PullRequestService.test.ts +1 -45
  24. package/src/services/PullRequestService.ts +1 -22
  25. package/src/services/PushService.test.ts +29 -295
  26. package/src/services/PushService.ts +10 -239
  27. package/src/services/RepositoryService.test.ts +1 -61
  28. package/src/services/RepositoryService.ts +2 -13
  29. package/src/services/ReviewService.test.ts +1 -84
  30. package/src/services/ReviewService.ts +9 -48
  31. package/src/services/SyncService.test.ts +0 -81
  32. package/src/services/SyncService.ts +12 -39
  33. package/src/services/TaskPhaseService.test.ts +0 -80
  34. package/src/services/TaskService.ts +1 -9
  35. package/src/services/VersionControlService.test.ts +4 -117
  36. package/src/services/VersionControlService.ts +3 -426
  37. package/src/services/WorkbaseService.test.ts +0 -20
  38. package/src/services/WorkbaseService.ts +1 -18
  39. package/src/services/WorktreeService.test.ts +1 -705
  40. package/src/services/WorktreeService.ts +395 -1604
  41. package/src/services/push-validation.ts +0 -7
  42. package/src/test-utils.ts +0 -4
  43. package/src/workbase/AGENTS.md +4 -5
  44. package/src/workbase/checkout-command.test.ts +1 -1
  45. package/src/workbase/checkout-command.ts +1 -1
  46. package/src/workbase/delivery-command.test.ts +4 -35
  47. package/src/workbase/delivery-command.ts +2 -15
  48. package/src/workbase/schemas.test.ts +0 -19
  49. package/src/workbase/schemas.ts +1 -2
  50. package/src/commands/vcs.test.ts +0 -75
  51. package/src/commands/vcs.ts +0 -72
  52. package/src/services/VcsMigrationService.test.ts +0 -348
  53. package/src/services/VcsMigrationService.ts +0 -857
  54. package/src/vcs-status-fast.ts +0 -310
  55. package/src/workbase/version-control.ts +0 -5
  56. package/src/workbase/workspace-command.test.ts +0 -70
  57. package/src/workbase/workspace-command.ts +0 -63
@@ -3,11 +3,8 @@ import { resolve } from "node:path"
3
3
  import { ContextService } from "../services/ContextService"
4
4
  import { FileSystemService } from "../services/FileSystemService"
5
5
  import { PullRequestService } from "../services/PullRequestService"
6
- import { VersionControlService } from "../services/VersionControlService"
7
- import { WorkbaseService } from "../services/WorkbaseService"
8
6
  import type { BaseCommandOptions } from "../utils/command"
9
7
  import { createLoggers } from "../utils/effect"
10
- import { repositoryFromRemote } from "../workbase/delivery-command"
11
8
 
12
9
  interface PrCreateOptions extends BaseCommandOptions {
13
10
  readonly taskId: string
@@ -20,56 +17,6 @@ interface PrCreateOptions extends BaseCommandOptions {
20
17
  readonly labels?: readonly string[]
21
18
  }
22
19
 
23
- const branchTargetCommands = new Set([
24
- "checkout",
25
- "checks",
26
- "close",
27
- "comment",
28
- "diff",
29
- "edit",
30
- "lock",
31
- "merge",
32
- "ready",
33
- "reopen",
34
- "revert",
35
- "review",
36
- "unlock",
37
- "update-branch",
38
- "view",
39
- ])
40
-
41
- const hasOption = (args: readonly string[], short: string, long: string) =>
42
- args.some(
43
- (argument) =>
44
- argument === short ||
45
- argument.startsWith(`${short}=`) ||
46
- argument === long ||
47
- argument.startsWith(`${long}=`),
48
- )
49
-
50
- const withJjContext = (
51
- args: readonly string[],
52
- branch: string,
53
- repository: string,
54
- ) => {
55
- const [command, ...rest] = args
56
- if (!command) return args
57
-
58
- const branchArgs =
59
- (command === "create" || command === "new") &&
60
- !hasOption(rest, "-H", "--head")
61
- ? ["--head", branch]
62
- : branchTargetCommands.has(command) &&
63
- (rest.length === 0 || rest[0]?.startsWith("-"))
64
- ? [branch]
65
- : []
66
- const repositoryArgs = hasOption(rest, "-R", "--repo")
67
- ? []
68
- : ["--repo", repository]
69
-
70
- return [command, ...branchArgs, ...repositoryArgs, ...rest]
71
- }
72
-
73
20
  export const prCreate = (options: PrCreateOptions) =>
74
21
  Effect.gen(function* () {
75
22
  const pullRequests = yield* PullRequestService
@@ -88,8 +35,6 @@ export const pr = (args: readonly string[], cwd: string = process.cwd()) =>
88
35
  Effect.gen(function* () {
89
36
  const contexts = yield* ContextService
90
37
  const fs = yield* FileSystemService
91
- const workbase = yield* WorkbaseService
92
- const versionControl = yield* VersionControlService
93
38
  const invocationCwd = resolve(cwd)
94
39
  const context = yield* contexts
95
40
  .get({ cwd: invocationCwd, target: ".", compact: true })
@@ -104,30 +49,9 @@ export const pr = (args: readonly string[], cwd: string = process.cwd()) =>
104
49
  : null
105
50
  const focusedCheckout = writableCheckout ?? reviewCheckout
106
51
  const focusedCwd = focusedCheckout ?? invocationCwd
107
- let forwardedArgs = args
108
- let environment: Record<string, string> = {}
109
- if (focusedCheckout && context?.workbase.vcs === "jj") {
110
- if (writableCheckout && context.authority.writable) {
111
- const execution =
112
- context.documents?.phase?.data ?? context.documents?.task?.data
113
- const { config } = yield* workbase.loadConfig(context.workbase.root)
114
- const remote =
115
- config.repositories?.[context.authority.writable.repo]?.remote
116
- if (execution && "branch" in execution && remote) {
117
- forwardedArgs = withJjContext(
118
- args,
119
- execution.branch,
120
- repositoryFromRemote(remote),
121
- )
122
- }
123
- }
124
- const backend = yield* versionControl.forWorkbase(context.workbase.root)
125
- environment = yield* backend.gitEnvironment(focusedCheckout)
126
- }
127
- const result = yield* fs.runCommand(["gh", "pr", ...forwardedArgs], {
52
+ const result = yield* fs.runCommand(["gh", "pr", ...args], {
128
53
  cwd: focusedCwd,
129
54
  passthrough: true,
130
- env: environment,
131
55
  })
132
56
  return result.exitCode
133
57
  })
@@ -139,8 +63,7 @@ Usage: agency pr create <task-id> [phase-id] [options]
139
63
  Create records a pull request for an Agency execution unit and accepts the
140
64
  options listed below. Invocations without an Agency task target run gh pr
141
65
  unchanged, focusing the writable repository checkout when invoked from
142
- an Agency execution task or phase. In jj workbases, Agency supplies the declared
143
- branch and repository to gh subcommands that would otherwise infer Git context.
66
+ an Agency execution task or phase.
144
67
 
145
68
  Options:
146
69
  --draft Create the pull request as a draft
@@ -14,13 +14,12 @@ describe("push command", () => {
14
14
  fail: (message) => updates.push(`fail:${message}`),
15
15
  }
16
16
  const result = {
17
- vcs: "jj" as const,
17
+ vcs: "git" as const,
18
18
  taskId: "example",
19
19
  branch: "task/example",
20
20
  base: "main",
21
21
  remote: "origin",
22
22
  tip: "abc123",
23
- changeId: "change",
24
23
  }
25
24
  const logs = await captureLogs(() =>
26
25
  Effect.runPromise(
@@ -57,7 +57,7 @@ export const GraphReadiness = Schema.Struct({
57
57
 
58
58
  export const GraphWorkbase = Schema.Struct({
59
59
  version: Schema.Literal(2),
60
- vcs: Schema.optional(Schema.Literal("git", "jj")),
60
+ vcs: Schema.optional(Schema.Literal("git")),
61
61
  root: Schema.optional(Schema.String),
62
62
  })
63
63
 
@@ -1,6 +1,6 @@
1
1
  import { afterEach, beforeEach, describe, expect, test } from "bun:test"
2
2
  import { Effect } from "effect"
3
- import { chmod, mkdir, rm } from "node:fs/promises"
3
+ import { chmod, mkdir } from "node:fs/promises"
4
4
  import { join } from "node:path"
5
5
  import { cleanupTempDir, createTempDir, runTestEffect } from "../test-utils"
6
6
  import { ArchiveService } from "./ArchiveService"
@@ -17,13 +17,6 @@ const git = (args: readonly string[], cwd?: string) => {
17
17
  }
18
18
  }
19
19
 
20
- const jj = (args: readonly string[], cwd?: string) => {
21
- const result = Bun.spawnSync(["jj", ...args], { cwd })
22
- if (result.exitCode !== 0) {
23
- throw new Error(new TextDecoder().decode(result.stderr))
24
- }
25
- }
26
-
27
20
  describe("ArchiveService bulk task archive", () => {
28
21
  let root: string
29
22
  let source: string
@@ -430,140 +423,6 @@ claim:
430
423
  ])
431
424
  })
432
425
 
433
- test("skips a dirty jj workspace", async () => {
434
- if (!Bun.which("jj")) return
435
- const repository = join(root, "repos/agency")
436
- await rm(repository, { recursive: true, force: true })
437
- git(["clone", source, repository])
438
- const initialized = Bun.spawnSync([
439
- "jj",
440
- "git",
441
- "init",
442
- "--colocate",
443
- repository,
444
- ])
445
- if (initialized.exitCode !== 0) {
446
- throw new Error(new TextDecoder().decode(initialized.stderr))
447
- }
448
- await Bun.write(
449
- join(root, "agency.json"),
450
- JSON.stringify({ version: 2, vcs: "jj" }),
451
- )
452
- await createTask("jj-dirty")
453
- await dropTask("jj-dirty")
454
- const workspace = await runTestEffect(
455
- WorktreeService.pipe(
456
- Effect.flatMap((service) =>
457
- service.materialize("jj-dirty", undefined, root),
458
- ),
459
- ),
460
- )
461
- await Bun.write(join(workspace.writablePath!, "dirty.txt"), "keep\n")
462
-
463
- const result = await archiveTasks()
464
-
465
- expect(result.tasks[0]).toMatchObject({
466
- id: "jj-dirty",
467
- disposition: "skipped",
468
- reason: { code: "dirty-worktree" },
469
- })
470
- expect(
471
- await Bun.file(join(workspace.writablePath!, "dirty.txt")).exists(),
472
- ).toBe(true)
473
- })
474
-
475
- test("archives a jj working-copy commit preserved by its task bookmark", async () => {
476
- if (!Bun.which("jj")) return
477
- const repository = join(root, "repos/agency")
478
- await rm(repository, { recursive: true, force: true })
479
- git(["clone", source, repository])
480
- jj(["git", "init", "--colocate", repository])
481
- await Bun.write(
482
- join(root, "agency.json"),
483
- JSON.stringify({ version: 2, vcs: "jj" }),
484
- )
485
- await createTask("jj-bookmarked")
486
- await dropTask("jj-bookmarked")
487
- const workspace = await runTestEffect(
488
- WorktreeService.pipe(
489
- Effect.flatMap((service) =>
490
- service.materialize("jj-bookmarked", undefined, root),
491
- ),
492
- ),
493
- )
494
- await Bun.write(join(workspace.writablePath!, "preserved.txt"), "keep\n")
495
- jj(
496
- ["bookmark", "set", "task/jj-bookmarked", "-r", "@"],
497
- workspace.writablePath!,
498
- )
499
-
500
- const preview = await archiveTasks(true)
501
- expect(preview.tasks[0]).toMatchObject({
502
- id: "jj-bookmarked",
503
- disposition: "planned",
504
- removedWorktrees: [workspace.writablePath!],
505
- })
506
- expect(
507
- await Bun.file(join(workspace.writablePath!, "preserved.txt")).text(),
508
- ).toBe("keep\n")
509
-
510
- const result = await archiveTasks()
511
- expect(result.tasks[0]).toMatchObject({
512
- id: "jj-bookmarked",
513
- disposition: "archived",
514
- })
515
- expect(await Bun.file(workspace.writablePath!).exists()).toBe(false)
516
- const preserved = Bun.spawnSync([
517
- "jj",
518
- "-R",
519
- repository,
520
- "file",
521
- "show",
522
- "-r",
523
- "task/jj-bookmarked",
524
- 'root:"preserved.txt"',
525
- ])
526
- if (preserved.exitCode !== 0) {
527
- throw new Error(preserved.stderr.toString())
528
- }
529
- expect(preserved.stdout.toString()).toBe("keep\n")
530
- })
531
-
532
- test("archives a forgotten jj workspace preserved by its task bookmark", async () => {
533
- if (!Bun.which("jj")) return
534
- const repository = join(root, "repos/agency")
535
- await rm(repository, { recursive: true, force: true })
536
- git(["clone", source, repository])
537
- jj(["git", "init", "--colocate", repository])
538
- await Bun.write(
539
- join(root, "agency.json"),
540
- JSON.stringify({ version: 2, vcs: "jj" }),
541
- )
542
- await createTask("jj-stale")
543
- await dropTask("jj-stale")
544
- const workspace = await runTestEffect(
545
- WorktreeService.pipe(
546
- Effect.flatMap((service) =>
547
- service.materialize("jj-stale", undefined, root),
548
- ),
549
- ),
550
- )
551
- await Bun.write(join(workspace.writablePath!, "preserved.txt"), "keep\n")
552
- jj(["bookmark", "set", "task/jj-stale", "-r", "@"], workspace.writablePath!)
553
- jj(["-R", repository, "workspace", "forget", "agency-jj-stale-task-agency"])
554
-
555
- const result = await archiveTasks(true)
556
-
557
- expect(result.tasks[0]).toMatchObject({
558
- id: "jj-stale",
559
- disposition: "planned",
560
- removedWorktrees: [workspace.writablePath!],
561
- })
562
- expect(
563
- await Bun.file(join(workspace.writablePath!, "preserved.txt")).text(),
564
- ).toBe("keep\n")
565
- })
566
-
567
426
  test("rolls back the entire cohort when application fails", async () => {
568
427
  await runTestEffect(
569
428
  EpicService.pipe(
@@ -1,6 +1,6 @@
1
1
  import { afterEach, beforeEach, describe, expect, test } from "bun:test"
2
2
  import { Effect } from "effect"
3
- import { mkdir, rm } from "node:fs/promises"
3
+ import { mkdir } from "node:fs/promises"
4
4
  import { join } from "node:path"
5
5
  import { cleanupTempDir, createTempDir, runTestEffect } from "../test-utils"
6
6
  import { ArchiveService } from "./ArchiveService"
@@ -22,17 +22,6 @@ const git = async (args: string[], cwd?: string) => {
22
22
  }
23
23
  }
24
24
 
25
- const jj = async (args: string[]) => {
26
- const process = Bun.spawn(["jj", ...args], {
27
- stdout: "pipe",
28
- stderr: "pipe",
29
- })
30
- await process.exited
31
- if (process.exitCode !== 0) {
32
- throw new Error(await new Response(process.stderr).text())
33
- }
34
- }
35
-
36
25
  describe("ArchiveService", () => {
37
26
  let root: string
38
27
  const dropTask = (id: string) =>
@@ -276,166 +265,6 @@ describe("ArchiveService", () => {
276
265
  ).toBe(0)
277
266
  })
278
267
 
279
- test("retries archive after a jj workspace was forgotten but not deleted", async () => {
280
- if (!Bun.which("jj")) return
281
- const repository = join(root, "repos/agency")
282
- await rm(repository, { recursive: true, force: true })
283
- await git(["clone", join(root, "source"), repository])
284
- await jj(["git", "init", "--colocate", repository])
285
- await Bun.write(
286
- join(root, "agency.json"),
287
- JSON.stringify({ version: 2, vcs: "jj" }),
288
- )
289
- await runTestEffect(
290
- TaskService.pipe(
291
- Effect.flatMap((service) =>
292
- service.create(
293
- {
294
- id: "interrupted",
295
- ticketUrl: null,
296
- repo: "agency",
297
- branch: "task/interrupted",
298
- base: "main",
299
- },
300
- root,
301
- ),
302
- ),
303
- ),
304
- )
305
- await runTestEffect(
306
- TaskService.pipe(
307
- Effect.flatMap((service) =>
308
- service.setStatus("interrupted", "dropped", root),
309
- ),
310
- ),
311
- )
312
- const workspace = await runTestEffect(
313
- WorktreeService.pipe(
314
- Effect.flatMap((service) =>
315
- service.materialize("interrupted", undefined, root),
316
- ),
317
- ),
318
- )
319
- await jj([
320
- "-R",
321
- repository,
322
- "workspace",
323
- "forget",
324
- "agency-interrupted-task-agency",
325
- ])
326
-
327
- const preview = await runTestEffect(
328
- ArchiveService.pipe(
329
- Effect.flatMap((service) =>
330
- service.archiveTask("interrupted", root, { dryRun: true }),
331
- ),
332
- ),
333
- )
334
- expect(preview.removedWorktrees).toEqual([workspace.writablePath!])
335
-
336
- await runTestEffect(
337
- ArchiveService.pipe(
338
- Effect.flatMap((service) => service.archiveTask("interrupted", root)),
339
- ),
340
- )
341
- expect(await Bun.file(workspace.writablePath!).exists()).toBe(false)
342
- expect(
343
- await Bun.file(join(root, "archive/tasks/interrupted/TASK.md")).exists(),
344
- ).toBe(true)
345
- })
346
-
347
- test("refuses a modified residual jj checkout after workspace removal", async () => {
348
- if (!Bun.which("jj")) return
349
- const repository = join(root, "repos/agency")
350
- await rm(repository, { recursive: true, force: true })
351
- await git(["clone", join(root, "source"), repository])
352
- await jj(["git", "init", "--colocate", repository])
353
- await Bun.write(
354
- join(root, "agency.json"),
355
- JSON.stringify({ version: 2, vcs: "jj" }),
356
- )
357
- await runTestEffect(
358
- TaskService.pipe(
359
- Effect.flatMap((service) =>
360
- service.create(
361
- {
362
- id: "modified-residual",
363
- ticketUrl: null,
364
- repo: "agency",
365
- branch: "task/modified-residual",
366
- base: "main",
367
- },
368
- root,
369
- ),
370
- ),
371
- ),
372
- )
373
- await runTestEffect(
374
- TaskService.pipe(
375
- Effect.flatMap((service) =>
376
- service.setStatus("modified-residual", "dropped", root),
377
- ),
378
- ),
379
- )
380
- const workspace = await runTestEffect(
381
- WorktreeService.pipe(
382
- Effect.flatMap((service) =>
383
- service.materialize("modified-residual", undefined, root),
384
- ),
385
- ),
386
- )
387
- await jj([
388
- "-R",
389
- repository,
390
- "workspace",
391
- "forget",
392
- "agency-modified-residual-task-agency",
393
- ])
394
- await Bun.write(join(workspace.writablePath!, "keep.txt"), "keep me\n")
395
-
396
- await expect(
397
- runTestEffect(
398
- ArchiveService.pipe(
399
- Effect.flatMap((service) =>
400
- service.archiveTask("modified-residual", root),
401
- ),
402
- ),
403
- ),
404
- ).rejects.toThrow("contents do not match expected revision")
405
- expect(
406
- await Bun.file(join(workspace.writablePath!, "keep.txt")).text(),
407
- ).toBe("keep me\n")
408
- expect(
409
- await Bun.file(join(root, "tasks/modified-residual/TASK.md")).exists(),
410
- ).toBe(true)
411
- expect(
412
- await Bun.file(
413
- join(
414
- root,
415
- `.agency-worktree-${Buffer.from("modified-residual:task").toString("hex")}.lock`,
416
- ),
417
- ).exists(),
418
- ).toBe(false)
419
-
420
- await rm(join(workspace.writablePath!, "keep.txt"))
421
- await rm(join(workspace.writablePath!, ".jj"), {
422
- recursive: true,
423
- force: true,
424
- })
425
- await expect(
426
- runTestEffect(
427
- ArchiveService.pipe(
428
- Effect.flatMap((service) =>
429
- service.archiveTask("modified-residual", root),
430
- ),
431
- ),
432
- ),
433
- ).rejects.toThrow("is not registered as a jj workspace")
434
- expect(
435
- await Bun.file(join(workspace.writablePath!, "README.md")).exists(),
436
- ).toBe(true)
437
- })
438
-
439
268
  test("archives a phase in the mirrored task hierarchy", async () => {
440
269
  await runTestEffect(
441
270
  TaskService.pipe(
@@ -13,7 +13,6 @@ import {
13
13
  } from "./WorktreeService"
14
14
  import {
15
15
  GitVersionControlService,
16
- JjVersionControlService,
17
16
  VersionControlService,
18
17
  } from "./VersionControlService"
19
18
  import {
@@ -368,7 +367,6 @@ const WorktreeLayer = Layer.mergeAll(
368
367
  FileSystemService.Default,
369
368
  WorkbaseService.Default,
370
369
  GitVersionControlService.Default,
371
- JjVersionControlService.Default,
372
370
  VersionControlService.Default,
373
371
  TaskService.Default,
374
372
  PhaseService.Default,
@@ -400,22 +398,6 @@ const restoreWorktreeSnapshots = async (
400
398
  continue
401
399
  } catch {}
402
400
  await mkdir(dirname(snapshot.path), { recursive: true })
403
- if (snapshot.vcs === "jj") {
404
- await runGit([
405
- "jj",
406
- "-R",
407
- snapshot.repositoryPath,
408
- "workspace",
409
- "add",
410
- "--name",
411
- snapshot.workspaceName!,
412
- "-r",
413
- snapshot.head,
414
- snapshot.path,
415
- ])
416
- await runGit(["jj", "-R", snapshot.path, "edit", snapshot.head])
417
- continue
418
- }
419
401
  await runGit(
420
402
  snapshot.branch
421
403
  ? [
@@ -724,7 +706,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
724
706
  removedWorktrees.push(
725
707
  ...(yield* worktrees.remove(unit.taskId, unit.phaseId, root, {
726
708
  dryRun: true,
727
- persistResume: false,
728
709
  })),
729
710
  )
730
711
  }
@@ -783,7 +764,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
783
764
  worktrees.remove(unit.taskId, unit.phaseId, root, {
784
765
  snapshots,
785
766
  lockHeld: true,
786
- persistResume: false,
787
767
  }),
788
768
  )
789
769
  } catch (cause) {
@@ -897,7 +877,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
897
877
  const result = yield* worktrees
898
878
  .remove(unit.taskId, executionPhaseId(unit), root, {
899
879
  dryRun: true,
900
- persistResume: false,
901
880
  task: context.task,
902
881
  phase: unit.phaseId
903
882
  ? context.phases.find((phase) => phase.id === unit.phaseId)
@@ -1075,7 +1054,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
1075
1054
  worktrees.remove(unit.taskId, unit.phaseId, root, {
1076
1055
  snapshots,
1077
1056
  lockHeld: true,
1078
- persistResume: false,
1079
1057
  task: contexts.get(unit.taskId)!.task,
1080
1058
  phase: unit.phaseId
1081
1059
  ? contexts
@@ -1232,7 +1210,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
1232
1210
  root,
1233
1211
  {
1234
1212
  dryRun: true,
1235
- persistResume: false,
1236
1213
  },
1237
1214
  )),
1238
1215
  )
@@ -1288,7 +1265,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
1288
1265
  {
1289
1266
  snapshots,
1290
1267
  lockHeld: true,
1291
- persistResume: false,
1292
1268
  },
1293
1269
  ),
1294
1270
  )
@@ -1381,7 +1357,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
1381
1357
  yield* rejectExistingDestination(destination, "Archive")
1382
1358
  const removedWorktrees = yield* worktrees.remove(taskId, id, root, {
1383
1359
  dryRun: true,
1384
- persistResume: false,
1385
1360
  })
1386
1361
  const at = new Date().toISOString()
1387
1362
  const content = yield* declarationContent(task, {
@@ -1430,7 +1405,6 @@ export class ArchiveService extends Effect.Service<ArchiveService>()(
1430
1405
  worktrees.remove(taskId, id, root, {
1431
1406
  snapshots,
1432
1407
  lockHeld: true,
1433
- persistResume: false,
1434
1408
  }),
1435
1409
  )
1436
1410
  },
@@ -350,7 +350,7 @@ export class ContextService extends Effect.Service<ContextService>()(
350
350
  root,
351
351
  configPath: join(root, "agency.json"),
352
352
  version: config.version,
353
- vcs: config.vcs ?? "git",
353
+ vcs: "git",
354
354
  },
355
355
  target: { kind: "workbase", path: root },
356
356
  hint: compact
@@ -1025,51 +1025,9 @@ export class ContextService extends Effect.Service<ContextService>()(
1025
1025
  const inspectCheckout = (
1026
1026
  repositoryPath: string,
1027
1027
  checkoutPath: string,
1028
- expectedBranch: string | null = null,
1029
- branchCommit: string | null = null,
1030
1028
  ) =>
1031
1029
  Effect.gen(function* (): Generator<any, CheckoutInspection, any> {
1032
1030
  const materialized = yield* fs.isDirectory(checkoutPath)
1033
- if (backend.kind === "jj") {
1034
- const listed = yield* Effect.either(
1035
- backend.listWorkspaces(repositoryPath),
1036
- )
1037
- const workspaces = Either.isRight(listed) ? listed.right : []
1038
- if (Either.isLeft(listed)) {
1039
- inspectionWarnings.push(
1040
- `Unable to inspect jj workspace registrations for ${repositoryPath}`,
1041
- )
1042
- }
1043
- const canonicalCheckoutPath = materialized
1044
- ? yield* fs.realPath(checkoutPath)
1045
- : resolve(checkoutPath)
1046
- const workspace = workspaces.find(
1047
- (workspace) => workspace.path === canonicalCheckoutPath,
1048
- )
1049
- const registered = workspace !== undefined
1050
- if (!materialized) {
1051
- return {
1052
- materialized: false,
1053
- registered,
1054
- checkoutCommit: null,
1055
- checkoutBranch: null,
1056
- detached: null,
1057
- dirty: null,
1058
- }
1059
- }
1060
- return {
1061
- materialized: true,
1062
- registered,
1063
- checkoutCommit: workspace?.commit ?? null,
1064
- checkoutBranch:
1065
- expectedBranch && branchCommit === workspace?.commit
1066
- ? expectedBranch
1067
- : null,
1068
- detached:
1069
- !expectedBranch || branchCommit !== workspace?.commit,
1070
- dirty: workspace ? false : null,
1071
- }
1072
- }
1073
1031
  const listed = yield* runGit(fs, repositoryPath, [
1074
1032
  "worktree",
1075
1033
  "list",
@@ -1136,7 +1094,7 @@ export class ContextService extends Effect.Service<ContextService>()(
1136
1094
  const repositoryPath =
1137
1095
  repository?.path ?? join(root, "repos", executionData.repo)
1138
1096
  const checkoutPath = join(codePath, executionData.repo)
1139
- let branchCommit = yield* backend.resolveRevision(
1097
+ const branchCommit = yield* backend.resolveRevision(
1140
1098
  repositoryPath,
1141
1099
  executionData.branch,
1142
1100
  )
@@ -1147,8 +1105,6 @@ export class ContextService extends Effect.Service<ContextService>()(
1147
1105
  const checkout = yield* inspectCheckout(
1148
1106
  repositoryPath,
1149
1107
  checkoutPath,
1150
- executionData.branch,
1151
- branchCommit,
1152
1108
  )
1153
1109
  if (branchCommit === null) {
1154
1110
  inspectionWarnings.push(
@@ -1261,7 +1217,7 @@ export class ContextService extends Effect.Service<ContextService>()(
1261
1217
  root,
1262
1218
  configPath: join(root, "agency.json"),
1263
1219
  version: config.version,
1264
- vcs: config.vcs ?? "git",
1220
+ vcs: "git",
1265
1221
  },
1266
1222
  target,
1267
1223
  documents: {