@markjaquith/agency 1.11.0 → 2.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 (130) hide show
  1. package/README.md +302 -113
  2. package/cli.ts +123 -415
  3. package/index.ts +1 -1
  4. package/package.json +12 -17
  5. package/skills/agency/SKILL.md +258 -0
  6. package/src/cli.test.ts +290 -0
  7. package/src/commands/description.test.ts +103 -0
  8. package/src/commands/epic.test.ts +103 -0
  9. package/src/commands/epic.ts +101 -0
  10. package/src/commands/init.test.ts +42 -290
  11. package/src/commands/init.ts +15 -123
  12. package/src/commands/phase.ts +120 -0
  13. package/src/commands/pr.test.ts +19 -170
  14. package/src/commands/pr.ts +23 -179
  15. package/src/commands/repo.test.ts +80 -0
  16. package/src/commands/repo.ts +83 -0
  17. package/src/commands/status.test.ts +35 -477
  18. package/src/commands/status.ts +24 -213
  19. package/src/commands/task-phase.test.ts +206 -0
  20. package/src/commands/task.ts +83 -1285
  21. package/src/commands/validate.test.ts +91 -0
  22. package/src/commands/validate.ts +50 -0
  23. package/src/commands/work.test.ts +172 -419
  24. package/src/commands/work.ts +47 -166
  25. package/src/services/EpicService.test.ts +71 -0
  26. package/src/services/EpicService.ts +135 -0
  27. package/src/services/FileSystemService.ts +61 -92
  28. package/src/services/PhaseService.ts +323 -0
  29. package/src/services/PullRequestService.test.ts +386 -0
  30. package/src/services/PullRequestService.ts +143 -0
  31. package/src/services/RepositoryService.test.ts +106 -0
  32. package/src/services/RepositoryService.ts +159 -0
  33. package/src/services/TaskPhaseService.test.ts +217 -0
  34. package/src/services/TaskService.ts +192 -0
  35. package/src/services/WorkbaseService.test.ts +446 -0
  36. package/src/services/WorkbaseService.ts +493 -0
  37. package/src/services/WorktreeService.test.ts +599 -0
  38. package/src/services/WorktreeService.ts +357 -0
  39. package/src/test-utils.ts +41 -438
  40. package/src/types.ts +1 -215
  41. package/src/utils/command.ts +1 -5
  42. package/src/utils/effect.test.ts +24 -0
  43. package/src/utils/effect.ts +3 -273
  44. package/src/utils/process.test.ts +0 -15
  45. package/src/utils/process.ts +1 -60
  46. package/src/workbase/frontmatter.test.ts +50 -0
  47. package/src/workbase/frontmatter.ts +77 -0
  48. package/src/workbase/repository-reference.test.ts +25 -0
  49. package/src/workbase/repository-reference.ts +18 -0
  50. package/src/workbase/schemas.test.ts +146 -0
  51. package/src/workbase/schemas.ts +78 -0
  52. package/src/workbase/worktree-command.test.ts +61 -0
  53. package/src/workbase/worktree-command.ts +52 -0
  54. package/src/commands/base.test.ts +0 -198
  55. package/src/commands/base.ts +0 -198
  56. package/src/commands/clean.test.ts +0 -299
  57. package/src/commands/clean.ts +0 -274
  58. package/src/commands/completions.test.ts +0 -51
  59. package/src/commands/completions.ts +0 -308
  60. package/src/commands/emit.integration.test.ts +0 -549
  61. package/src/commands/emit.test.ts +0 -576
  62. package/src/commands/emit.ts +0 -700
  63. package/src/commands/emitted.test.ts +0 -226
  64. package/src/commands/emitted.ts +0 -57
  65. package/src/commands/loop.test.ts +0 -621
  66. package/src/commands/loop.ts +0 -406
  67. package/src/commands/merge.integration.test.ts +0 -195
  68. package/src/commands/merge.test.ts +0 -246
  69. package/src/commands/merge.ts +0 -244
  70. package/src/commands/pull.test.ts +0 -395
  71. package/src/commands/pull.ts +0 -205
  72. package/src/commands/push.test.ts +0 -518
  73. package/src/commands/push.ts +0 -434
  74. package/src/commands/rebase.test.ts +0 -521
  75. package/src/commands/rebase.ts +0 -232
  76. package/src/commands/save.test.ts +0 -247
  77. package/src/commands/save.ts +0 -162
  78. package/src/commands/source.test.ts +0 -195
  79. package/src/commands/source.ts +0 -72
  80. package/src/commands/switch.test.ts +0 -194
  81. package/src/commands/switch.ts +0 -84
  82. package/src/commands/task-branching.test.ts +0 -633
  83. package/src/commands/task-continue.test.ts +0 -311
  84. package/src/commands/task-edit.test.ts +0 -235
  85. package/src/commands/task-main.test.ts +0 -1066
  86. package/src/commands/task-squash.test.ts +0 -266
  87. package/src/commands/tasks.test.ts +0 -391
  88. package/src/commands/tasks.ts +0 -161
  89. package/src/commands/template-delete.test.ts +0 -178
  90. package/src/commands/template-delete.ts +0 -98
  91. package/src/commands/template-list.test.ts +0 -135
  92. package/src/commands/template-list.ts +0 -87
  93. package/src/commands/template-view.test.ts +0 -158
  94. package/src/commands/template-view.ts +0 -86
  95. package/src/commands/template.test.ts +0 -32
  96. package/src/commands/template.ts +0 -96
  97. package/src/commands/use.test.ts +0 -87
  98. package/src/commands/use.ts +0 -97
  99. package/src/constants.ts +0 -10
  100. package/src/errors.ts +0 -17
  101. package/src/schemas.ts +0 -33
  102. package/src/services/AgencyMetadataService.ts +0 -311
  103. package/src/services/ClaudeService.test.ts +0 -184
  104. package/src/services/ClaudeService.ts +0 -91
  105. package/src/services/ConfigService.ts +0 -115
  106. package/src/services/FilterRepoService.ts +0 -164
  107. package/src/services/FormatterService.test.ts +0 -432
  108. package/src/services/FormatterService.ts +0 -219
  109. package/src/services/GitService.ts +0 -1183
  110. package/src/services/MockFilterRepoService.ts +0 -140
  111. package/src/services/OpencodeService.ts +0 -263
  112. package/src/services/PromptService.ts +0 -183
  113. package/src/services/TemplateService.ts +0 -81
  114. package/src/types/native-exec.d.ts +0 -8
  115. package/src/utils/colors.ts +0 -178
  116. package/src/utils/git-path.ts +0 -6
  117. package/src/utils/glob.test.ts +0 -161
  118. package/src/utils/glob.ts +0 -78
  119. package/src/utils/paths.ts +0 -51
  120. package/src/utils/pr-branch.test.ts +0 -376
  121. package/src/utils/pr-branch.ts +0 -508
  122. package/src/utils/spinner.test.ts +0 -45
  123. package/src/utils/spinner.ts +0 -96
  124. package/src/utils/task-parser.test.ts +0 -172
  125. package/src/utils/task-parser.ts +0 -93
  126. package/templates/AGENCY.md +0 -22
  127. package/templates/AGENTS.md +0 -11
  128. package/templates/CLAUDE.md +0 -3
  129. package/templates/TASK.md +0 -5
  130. package/templates/opencode.json +0 -4
@@ -0,0 +1,91 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test"
2
+ import { mkdir } from "node:fs/promises"
3
+ import { join } from "node:path"
4
+ import {
5
+ captureLogs,
6
+ cleanupTempDir,
7
+ createTempDir,
8
+ runTestEffect,
9
+ } from "../test-utils"
10
+ import { validate } from "./validate"
11
+
12
+ describe("validate command", () => {
13
+ let root: string
14
+
15
+ beforeEach(async () => {
16
+ root = await createTempDir()
17
+ await Bun.write(join(root, "agency.json"), '{"version":2}\n')
18
+ await mkdir(join(root, "repos/agency"), { recursive: true })
19
+ await mkdir(join(root, "tasks/example"), { recursive: true })
20
+ })
21
+
22
+ afterEach(async () => {
23
+ await cleanupTempDir(root)
24
+ })
25
+
26
+ test("succeeds for a valid workbase", async () => {
27
+ await Bun.write(
28
+ join(root, "tasks/example/TASK.md"),
29
+ `---
30
+ ticketUrl: https://example.com/tasks/example
31
+ repo: agency
32
+ branch: task/example
33
+ base: main
34
+ pr: null
35
+ ---
36
+
37
+ # Example
38
+ `,
39
+ )
40
+
41
+ await expect(
42
+ runTestEffect(validate({ cwd: root, silent: true })),
43
+ ).resolves.toBeUndefined()
44
+ })
45
+
46
+ test("outputs the validation report as JSON", async () => {
47
+ await Bun.write(
48
+ join(root, "tasks/example/TASK.md"),
49
+ `---
50
+ ticketUrl: https://example.com/tasks/example
51
+ repo: agency
52
+ branch: task/example
53
+ base: main
54
+ pr: null
55
+ ---
56
+ `,
57
+ )
58
+ const logs = await captureLogs(() =>
59
+ runTestEffect(validate({ cwd: root, json: true })),
60
+ )
61
+
62
+ expect(JSON.parse(logs[0]!)).toEqual({
63
+ root,
64
+ issues: [],
65
+ epicCount: 0,
66
+ taskCount: 1,
67
+ phaseCount: 0,
68
+ valid: true,
69
+ })
70
+ })
71
+
72
+ test("fails with document diagnostics", async () => {
73
+ await Bun.write(
74
+ join(root, "tasks/example/TASK.md"),
75
+ `---
76
+ ticketUrl: https://example.com/tasks/example
77
+ repo: missing
78
+ branch: task/example
79
+ base: main
80
+ pr: null
81
+ ---
82
+
83
+ # Example
84
+ `,
85
+ )
86
+
87
+ await expect(
88
+ runTestEffect(validate({ cwd: root, silent: true })),
89
+ ).rejects.toThrow("Unknown repository alias 'missing'")
90
+ })
91
+ })
@@ -0,0 +1,50 @@
1
+ import { Data, Effect } from "effect"
2
+ import type { BaseCommandOptions } from "../utils/command"
3
+ import { WorkbaseService } from "../services/WorkbaseService"
4
+ import { createLoggers } from "../utils/effect"
5
+
6
+ interface ValidateOptions extends BaseCommandOptions {
7
+ readonly json?: boolean
8
+ }
9
+
10
+ class ValidationFailedError extends Data.TaggedError("ValidationFailedError")<{
11
+ readonly message: string
12
+ }> {}
13
+
14
+ export const validate = (options: ValidateOptions = {}) =>
15
+ Effect.gen(function* () {
16
+ const workbase = yield* WorkbaseService
17
+ const { log } = createLoggers(options)
18
+ const report = yield* workbase.validate(options.cwd ?? process.cwd())
19
+
20
+ if (options.json) {
21
+ log(JSON.stringify(report, null, 2))
22
+ }
23
+
24
+ if (!report.valid) {
25
+ const details = report.issues
26
+ .map((issue) => `- ${issue.path}: ${issue.message}`)
27
+ .join("\n")
28
+ return yield* new ValidationFailedError({
29
+ message: `Workbase validation failed with ${report.issues.length} issue${report.issues.length === 1 ? "" : "s"}:\n${details}`,
30
+ })
31
+ }
32
+
33
+ if (!options.json) {
34
+ log(
35
+ `Valid workbase: ${report.epicCount} epic${report.epicCount === 1 ? "" : "s"}, ` +
36
+ `${report.taskCount} task${report.taskCount === 1 ? "" : "s"}, ` +
37
+ `${report.phaseCount} phase${report.phaseCount === 1 ? "" : "s"}`,
38
+ )
39
+ }
40
+ })
41
+
42
+ export const help = `
43
+ Usage: agency validate [options]
44
+
45
+ Validate the current workbase configuration, frontmatter, references, and
46
+ dependency graphs.
47
+
48
+ Options:
49
+ --json Output the validation report as JSON
50
+ `