@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.
- package/README.md +23 -121
- 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 +0 -67
- 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 +3 -47
- 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/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 +4 -5
- 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
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
export interface PushCommitMetadata {
|
|
2
2
|
readonly commitId: string
|
|
3
|
-
readonly changeId?: string
|
|
4
3
|
readonly description: string
|
|
5
|
-
readonly empty: boolean
|
|
6
4
|
readonly authorName: string
|
|
7
5
|
readonly authorEmail: string
|
|
8
|
-
readonly conflict: boolean
|
|
9
|
-
readonly parents: readonly string[]
|
|
10
6
|
}
|
|
11
7
|
|
|
12
8
|
export const parseGitCommits = (
|
|
@@ -26,10 +22,7 @@ export const parseGitCommits = (
|
|
|
26
22
|
return {
|
|
27
23
|
commitId,
|
|
28
24
|
description,
|
|
29
|
-
empty: false,
|
|
30
25
|
authorName,
|
|
31
26
|
authorEmail,
|
|
32
|
-
conflict: false,
|
|
33
|
-
parents: [],
|
|
34
27
|
}
|
|
35
28
|
})
|
package/src/test-utils.ts
CHANGED
|
@@ -24,10 +24,8 @@ import { DoctorService } from "./services/DoctorService"
|
|
|
24
24
|
import { ReviewService } from "./services/ReviewService"
|
|
25
25
|
import {
|
|
26
26
|
GitVersionControlService,
|
|
27
|
-
JjVersionControlService,
|
|
28
27
|
VersionControlService,
|
|
29
28
|
} from "./services/VersionControlService"
|
|
30
|
-
import { VcsMigrationService } from "./services/VcsMigrationService"
|
|
31
29
|
|
|
32
30
|
export const createTempDir = () => mkdtemp(join(tmpdir(), "agency-test-"))
|
|
33
31
|
|
|
@@ -38,9 +36,7 @@ const TestLayer = Layer.mergeAll(
|
|
|
38
36
|
FileSystemService.Default,
|
|
39
37
|
WorkbaseService.Default,
|
|
40
38
|
GitVersionControlService.Default,
|
|
41
|
-
JjVersionControlService.Default,
|
|
42
39
|
VersionControlService.Default,
|
|
43
|
-
VcsMigrationService.Default,
|
|
44
40
|
RepositoryService.Default,
|
|
45
41
|
EpicService.Default,
|
|
46
42
|
TaskService.Default,
|
package/src/workbase/AGENTS.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Agency Workbase
|
|
2
2
|
|
|
3
3
|
This directory is an Agency workbase. Epics, tasks, and phases are durable
|
|
4
|
-
Markdown documents; repository aliases and generated Git worktrees
|
|
5
|
-
|
|
4
|
+
Markdown documents; repository aliases and generated Git worktrees provide code
|
|
5
|
+
access.
|
|
6
6
|
|
|
7
7
|
## Command Fast Paths
|
|
8
8
|
|
|
@@ -184,9 +184,8 @@ repository's formatting, type checks, build, dead-code checks, and focused tests
|
|
|
184
184
|
Review and commit the diff according to the repository's instructions.
|
|
185
185
|
|
|
186
186
|
Use `agency push` from an execution task or phase to validate and publish its
|
|
187
|
-
declared delivery branch
|
|
188
|
-
|
|
189
|
-
IDs and remediation commands before retrying.
|
|
187
|
+
declared delivery branch without creating a pull request. The command never authors semantic commit descriptions;
|
|
188
|
+
resolve its reported commits and remediation commands before retrying.
|
|
190
189
|
|
|
191
190
|
`agency work` is the human launch flow: it reconciles managed integration,
|
|
192
191
|
selects work, checks readiness, prepares checkouts, marks execution work
|
|
@@ -5,7 +5,7 @@ export interface CheckoutCommandVariables {
|
|
|
5
5
|
readonly checkoutKind: "writable" | "reference"
|
|
6
6
|
readonly requestedRef: string
|
|
7
7
|
readonly base: string
|
|
8
|
-
readonly vcs: "git"
|
|
8
|
+
readonly vcs: "git"
|
|
9
9
|
readonly workbaseRoot: string
|
|
10
10
|
readonly taskId: string
|
|
11
11
|
readonly phaseId: string
|
|
@@ -32,45 +32,18 @@ describe("delivery commands", () => {
|
|
|
32
32
|
})
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
test("
|
|
35
|
+
test("builds the default GitHub create command", () => {
|
|
36
36
|
const input = {
|
|
37
37
|
base: "main",
|
|
38
|
-
branch: "feat/example",
|
|
39
|
-
repository: "example/agency",
|
|
40
38
|
draft: false,
|
|
41
39
|
} as const
|
|
42
|
-
expect(
|
|
43
|
-
resolveGitHubCreateCommand({
|
|
44
|
-
...input,
|
|
45
|
-
vcs: "jj",
|
|
46
|
-
defaults: { title: "Add example", body: "Details" },
|
|
47
|
-
}),
|
|
48
|
-
).toEqual({
|
|
49
|
-
argv: [
|
|
50
|
-
"gh",
|
|
51
|
-
"pr",
|
|
52
|
-
"create",
|
|
53
|
-
"--title",
|
|
54
|
-
"Add example",
|
|
55
|
-
"--body",
|
|
56
|
-
"Details",
|
|
57
|
-
"--base",
|
|
58
|
-
"main",
|
|
59
|
-
"--head",
|
|
60
|
-
"feat/example",
|
|
61
|
-
"--repo",
|
|
62
|
-
"example/agency",
|
|
63
|
-
],
|
|
64
|
-
environment: {},
|
|
65
|
-
})
|
|
66
|
-
expect(resolveGitHubCreateCommand({ ...input, vcs: "git" })).toEqual({
|
|
40
|
+
expect(resolveGitHubCreateCommand(input)).toEqual({
|
|
67
41
|
argv: ["gh", "pr", "create", "--fill", "--base", "main"],
|
|
68
42
|
environment: {},
|
|
69
43
|
})
|
|
70
44
|
expect(
|
|
71
45
|
resolveGitHubCreateCommand({
|
|
72
46
|
...input,
|
|
73
|
-
vcs: "git",
|
|
74
47
|
head: "feat/example",
|
|
75
48
|
}),
|
|
76
49
|
).toEqual({
|
|
@@ -89,9 +62,8 @@ describe("delivery commands", () => {
|
|
|
89
62
|
expect(
|
|
90
63
|
resolveGitHubCreateCommand({
|
|
91
64
|
...input,
|
|
92
|
-
vcs: "jj",
|
|
93
|
-
defaults: { title: "Generated", body: "Details" },
|
|
94
65
|
title: "Requested",
|
|
66
|
+
head: "feat/example",
|
|
95
67
|
labels: ["ai-assisted", "platform"],
|
|
96
68
|
}),
|
|
97
69
|
).toEqual({
|
|
@@ -99,16 +71,13 @@ describe("delivery commands", () => {
|
|
|
99
71
|
"gh",
|
|
100
72
|
"pr",
|
|
101
73
|
"create",
|
|
74
|
+
"--fill",
|
|
102
75
|
"--title",
|
|
103
76
|
"Requested",
|
|
104
|
-
"--body",
|
|
105
|
-
"Details",
|
|
106
77
|
"--base",
|
|
107
78
|
"main",
|
|
108
79
|
"--head",
|
|
109
80
|
"feat/example",
|
|
110
|
-
"--repo",
|
|
111
|
-
"example/agency",
|
|
112
81
|
"--label",
|
|
113
82
|
"ai-assisted",
|
|
114
83
|
"--label",
|
|
@@ -20,21 +20,13 @@ export const repositoryFromRemote = (remote: string) =>
|
|
|
20
20
|
|
|
21
21
|
export const resolveGitHubCreateCommand = ({
|
|
22
22
|
base,
|
|
23
|
-
branch,
|
|
24
|
-
repository,
|
|
25
23
|
draft,
|
|
26
|
-
vcs,
|
|
27
|
-
defaults,
|
|
28
24
|
title,
|
|
29
25
|
head,
|
|
30
26
|
labels = [],
|
|
31
27
|
}: {
|
|
32
28
|
readonly base: string
|
|
33
|
-
readonly branch: string
|
|
34
|
-
readonly repository: string
|
|
35
29
|
readonly draft: boolean
|
|
36
|
-
readonly vcs: "git" | "jj"
|
|
37
|
-
readonly defaults?: { readonly title: string; readonly body: string }
|
|
38
30
|
readonly title?: string
|
|
39
31
|
readonly head?: string
|
|
40
32
|
readonly labels?: readonly string[]
|
|
@@ -43,15 +35,10 @@ export const resolveGitHubCreateCommand = ({
|
|
|
43
35
|
"gh",
|
|
44
36
|
"pr",
|
|
45
37
|
"create",
|
|
46
|
-
...(
|
|
47
|
-
? ["--title", title ?? defaults.title, "--body", defaults.body]
|
|
48
|
-
: title
|
|
49
|
-
? ["--fill", "--title", title]
|
|
50
|
-
: ["--fill"]),
|
|
38
|
+
...(title ? ["--fill", "--title", title] : ["--fill"]),
|
|
51
39
|
"--base",
|
|
52
40
|
base,
|
|
53
|
-
...(
|
|
54
|
-
...(vcs === "jj" ? ["--repo", repository] : []),
|
|
41
|
+
...(head ? ["--head", head] : []),
|
|
55
42
|
...(draft ? ["--draft"] : []),
|
|
56
43
|
...labels.flatMap((label) => ["--label", label]),
|
|
57
44
|
],
|
|
@@ -257,25 +257,6 @@ describe("repository post-checkout configuration", () => {
|
|
|
257
257
|
})
|
|
258
258
|
})
|
|
259
259
|
|
|
260
|
-
describe("workspace creation configuration", () => {
|
|
261
|
-
test("accepts a jj workspace argv command", () => {
|
|
262
|
-
const config = Schema.decodeUnknownSync(WorkbaseConfig)({
|
|
263
|
-
version: 2,
|
|
264
|
-
vcs: "jj",
|
|
265
|
-
workspaceCreateCommand: [
|
|
266
|
-
"prewarm",
|
|
267
|
-
"adopt",
|
|
268
|
-
"{repo}",
|
|
269
|
-
"{workspace}",
|
|
270
|
-
"{name}",
|
|
271
|
-
"{revision}",
|
|
272
|
-
],
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
expect(config.workspaceCreateCommand?.[0]).toBe("prewarm")
|
|
276
|
-
})
|
|
277
|
-
})
|
|
278
|
-
|
|
279
260
|
describe("agent configuration", () => {
|
|
280
261
|
test("accepts named argv commands with resume commands and environment", () => {
|
|
281
262
|
const config = Schema.decodeUnknownSync(WorkbaseConfig)({
|
package/src/workbase/schemas.ts
CHANGED
|
@@ -103,13 +103,12 @@ const DeliveryProvider = Schema.Struct({
|
|
|
103
103
|
|
|
104
104
|
export const WorkbaseConfig = Schema.Struct({
|
|
105
105
|
version: Schema.Literal(2),
|
|
106
|
-
vcs: Schema.optional(Schema.Literal("git"
|
|
106
|
+
vcs: Schema.optional(Schema.Literal("git")),
|
|
107
107
|
repositories: Schema.optional(
|
|
108
108
|
Schema.Record({ key: RepositoryAlias, value: RepositoryDeclaration }),
|
|
109
109
|
),
|
|
110
110
|
chooserCommand: Schema.optional(Schema.NonEmptyArray(NonEmptyString)),
|
|
111
111
|
worktreeCreateCommand: Schema.optional(Schema.NonEmptyArray(NonEmptyString)),
|
|
112
|
-
workspaceCreateCommand: Schema.optional(Schema.NonEmptyArray(NonEmptyString)),
|
|
113
112
|
agents: Schema.optional(
|
|
114
113
|
Schema.Record({
|
|
115
114
|
key: EntityId,
|
package/src/commands/vcs.test.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
|
2
|
-
import {
|
|
3
|
-
captureLogs,
|
|
4
|
-
cleanupTempDir,
|
|
5
|
-
createTempDir,
|
|
6
|
-
runTestEffect,
|
|
7
|
-
} from "../test-utils"
|
|
8
|
-
import { vcs } from "./vcs"
|
|
9
|
-
|
|
10
|
-
describe("vcs command", () => {
|
|
11
|
-
let root: string
|
|
12
|
-
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
root = await createTempDir()
|
|
15
|
-
await Bun.write(
|
|
16
|
-
`${root}/agency.json`,
|
|
17
|
-
JSON.stringify({ version: 2, vcs: "git" }),
|
|
18
|
-
)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(async () => cleanupTempDir(root))
|
|
22
|
-
|
|
23
|
-
test("reports structured backend status", async () => {
|
|
24
|
-
const logs = await captureLogs(() =>
|
|
25
|
-
runTestEffect(vcs({ subcommand: "status", cwd: root, json: true })),
|
|
26
|
-
)
|
|
27
|
-
expect(JSON.parse(logs[0]!)).toMatchObject({
|
|
28
|
-
root,
|
|
29
|
-
configured: "git",
|
|
30
|
-
source: "git",
|
|
31
|
-
target: "git",
|
|
32
|
-
workspaceCount: 0,
|
|
33
|
-
blockers: [],
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test("persists the inferred Git backend for a legacy workbase", async () => {
|
|
38
|
-
await Bun.write(`${root}/agency.json`, JSON.stringify({ version: 2 }))
|
|
39
|
-
await captureLogs(() =>
|
|
40
|
-
runTestEffect(
|
|
41
|
-
vcs({
|
|
42
|
-
subcommand: "migrate",
|
|
43
|
-
target: "git",
|
|
44
|
-
cwd: root,
|
|
45
|
-
apply: true,
|
|
46
|
-
json: true,
|
|
47
|
-
}),
|
|
48
|
-
),
|
|
49
|
-
)
|
|
50
|
-
expect(await Bun.file(`${root}/agency.json`).json()).toEqual({
|
|
51
|
-
version: 2,
|
|
52
|
-
vcs: "git",
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
test("treats migration to the configured backend as a no-op", async () => {
|
|
57
|
-
const logs = await captureLogs(() =>
|
|
58
|
-
runTestEffect(
|
|
59
|
-
vcs({
|
|
60
|
-
subcommand: "migrate",
|
|
61
|
-
target: "git",
|
|
62
|
-
cwd: root,
|
|
63
|
-
apply: true,
|
|
64
|
-
json: true,
|
|
65
|
-
}),
|
|
66
|
-
),
|
|
67
|
-
)
|
|
68
|
-
expect(JSON.parse(logs[0]!)).toMatchObject({
|
|
69
|
-
source: "git",
|
|
70
|
-
target: "git",
|
|
71
|
-
mode: "apply",
|
|
72
|
-
actions: [],
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
})
|
package/src/commands/vcs.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { Effect } from "effect"
|
|
2
|
-
import { VcsMigrationService } from "../services/VcsMigrationService"
|
|
3
|
-
import type { BaseCommandOptions } from "../utils/command"
|
|
4
|
-
import { createLoggers } from "../utils/effect"
|
|
5
|
-
|
|
6
|
-
interface VcsOptions extends BaseCommandOptions {
|
|
7
|
-
readonly subcommand?: string
|
|
8
|
-
readonly target?: string
|
|
9
|
-
readonly apply?: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const vcs = (options: VcsOptions = {}) =>
|
|
13
|
-
Effect.gen(function* () {
|
|
14
|
-
const migrations = yield* VcsMigrationService
|
|
15
|
-
const { log } = createLoggers(options)
|
|
16
|
-
const root = options.cwd ?? process.cwd()
|
|
17
|
-
if (options.subcommand === "status") {
|
|
18
|
-
const status = yield* migrations.status(root)
|
|
19
|
-
if (options.json) return log(JSON.stringify(status, null, 2))
|
|
20
|
-
log(
|
|
21
|
-
`Version control: ${status.source}${status.configured ? "" : " (inferred for legacy workbase)"}`,
|
|
22
|
-
)
|
|
23
|
-
log(
|
|
24
|
-
`Tools: git=${status.available.git ? "available" : "missing"} jj=${status.available.jj ? "available" : "missing"}`,
|
|
25
|
-
)
|
|
26
|
-
log(
|
|
27
|
-
`Repositories: ${status.repositories.length}; managed workspaces: ${status.workspaceCount}; blockers: ${status.blockers.length}`,
|
|
28
|
-
)
|
|
29
|
-
for (const blocker of status.blockers)
|
|
30
|
-
log(`blocker ${blocker.kind} ${blocker.target}: ${blocker.message}`)
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
if (options.subcommand === "migrate") {
|
|
34
|
-
if (options.target !== "git" && options.target !== "jj") {
|
|
35
|
-
return yield* Effect.fail(
|
|
36
|
-
new Error("VCS migration target must be 'git' or 'jj'"),
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
const result = yield* migrations.migrate(options.target, root, {
|
|
40
|
-
apply: options.apply,
|
|
41
|
-
})
|
|
42
|
-
if (options.json) return log(JSON.stringify(result, null, 2))
|
|
43
|
-
log(
|
|
44
|
-
result.mode === "apply"
|
|
45
|
-
? `Migrated workbase to ${options.target}`
|
|
46
|
-
: `Migration plan: ${result.source} -> ${options.target}`,
|
|
47
|
-
)
|
|
48
|
-
for (const action of result.actions) log(`- ${action}`)
|
|
49
|
-
if (result.mode === "dry-run" && result.actions.length > 0)
|
|
50
|
-
log("Run again with --apply to perform the migration.")
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
return yield* Effect.fail(
|
|
54
|
-
new Error(`Unknown vcs subcommand '${options.subcommand ?? ""}'`),
|
|
55
|
-
)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
export const help = `
|
|
59
|
-
Usage: agency vcs <status|migrate>
|
|
60
|
-
|
|
61
|
-
Inspect or migrate the workbase-wide version-control backend.
|
|
62
|
-
|
|
63
|
-
Commands:
|
|
64
|
-
status Show the configured backend, tools, repositories, and blockers
|
|
65
|
-
migrate <git|jj> [--dry-run | --apply]
|
|
66
|
-
Preview or apply a clean, transactional backend migration
|
|
67
|
-
|
|
68
|
-
Options:
|
|
69
|
-
--apply Apply the migration; omission performs a dry run
|
|
70
|
-
--dry-run Explicitly preview the migration without applying it
|
|
71
|
-
--json Print structured output
|
|
72
|
-
`
|