@markjaquith/agency 2.12.0 → 2.14.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 +46 -7
- package/cli.ts +72 -3
- package/package.json +1 -1
- package/schemas/agency-graph-v1.schema.json +28 -1
- package/skills/agency/SKILL.md +14 -3
- package/src/cli-parser.test.ts +97 -0
- package/src/cli-parser.ts +100 -4
- package/src/cli.test.ts +155 -0
- package/src/commands/claim.ts +97 -0
- package/src/commands/phase.ts +1 -1
- package/src/commands/task-phase.test.ts +4 -4
- package/src/commands/task.ts +1 -1
- package/src/commands/work.test.ts +65 -1
- package/src/commands/work.ts +94 -5
- package/src/protocol.test.ts +25 -0
- package/src/protocol.ts +16 -0
- package/src/services/ClaimService.test.ts +270 -0
- package/src/services/ClaimService.ts +446 -0
- package/src/services/PhaseService.ts +13 -0
- package/src/services/TaskPhaseService.test.ts +10 -9
- package/src/services/TaskService.ts +11 -0
- package/src/services/WorktreeService.test.ts +82 -7
- package/src/services/WorktreeService.ts +199 -41
- package/src/test-utils.ts +2 -0
- package/src/utils/command.ts +1 -0
- package/src/workbase/AGENTS.md +2 -2
- package/src/workbase/document-revision.ts +2 -0
- package/src/workbase/frontmatter.ts +59 -53
- package/src/workbase/schemas.test.ts +27 -0
- package/src/workbase/schemas.ts +21 -0
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
|
|
|
2
2
|
import { Schema } from "@effect/schema"
|
|
3
3
|
import {
|
|
4
4
|
EntityId,
|
|
5
|
+
ClaimRecord,
|
|
5
6
|
EpicFrontmatter,
|
|
6
7
|
PhaseFrontmatter,
|
|
7
8
|
TaskFrontmatter,
|
|
@@ -154,6 +155,32 @@ describe("work status", () => {
|
|
|
154
155
|
})
|
|
155
156
|
})
|
|
156
157
|
|
|
158
|
+
describe("claim records", () => {
|
|
159
|
+
const record = {
|
|
160
|
+
claimant: "orchestrator",
|
|
161
|
+
runner: "agent",
|
|
162
|
+
sessionId: "job-1",
|
|
163
|
+
startedAt: "2026-07-17T12:00:00.000Z",
|
|
164
|
+
targetRevision: "0".repeat(64),
|
|
165
|
+
expiresAt: "2026-07-17T13:00:00.000Z",
|
|
166
|
+
state: "active" as const,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
test("accepts explicit ownership and revision metadata", () => {
|
|
170
|
+
expect(Schema.decodeUnknownSync(ClaimRecord)(record)).toEqual(record)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test("rejects malformed timestamps, revisions, and empty identities", () => {
|
|
174
|
+
for (const invalid of [
|
|
175
|
+
{ ...record, claimant: "" },
|
|
176
|
+
{ ...record, startedAt: "today" },
|
|
177
|
+
{ ...record, targetRevision: "abc" },
|
|
178
|
+
]) {
|
|
179
|
+
expect(() => Schema.decodeUnknownSync(ClaimRecord)(invalid)).toThrow()
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
|
|
157
184
|
describe("workbase registry", () => {
|
|
158
185
|
test("accepts registered paths", () => {
|
|
159
186
|
expect(
|
package/src/workbase/schemas.ts
CHANGED
|
@@ -23,6 +23,25 @@ export const WorkStatus = Schema.Literal(
|
|
|
23
23
|
"dropped",
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
+
const IsoTimestamp = NonEmptyString.pipe(
|
|
27
|
+
Schema.pattern(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const DocumentRevision = Schema.String.pipe(Schema.pattern(/^[a-f0-9]{64}$/))
|
|
31
|
+
|
|
32
|
+
export const ClaimRecord = Schema.Struct({
|
|
33
|
+
claimant: NonEmptyString,
|
|
34
|
+
runner: NonEmptyString,
|
|
35
|
+
sessionId: NonEmptyString,
|
|
36
|
+
startedAt: IsoTimestamp,
|
|
37
|
+
targetRevision: DocumentRevision,
|
|
38
|
+
expiresAt: Schema.optional(IsoTimestamp),
|
|
39
|
+
state: Schema.Literal("active", "released", "finished"),
|
|
40
|
+
releasedAt: Schema.optional(IsoTimestamp),
|
|
41
|
+
finishedAt: Schema.optional(IsoTimestamp),
|
|
42
|
+
outcome: Schema.optional(Schema.Literal("done", "dropped")),
|
|
43
|
+
})
|
|
44
|
+
|
|
26
45
|
const Url = NonEmptyString.pipe(Schema.pattern(/^[a-zA-Z][a-zA-Z0-9+.-]*:/))
|
|
27
46
|
|
|
28
47
|
const GitHubPullRequestUrl = NonEmptyString.pipe(
|
|
@@ -51,6 +70,7 @@ const ExecutionUnit = {
|
|
|
51
70
|
base: NonEmptyString,
|
|
52
71
|
pr: Schema.NullOr(GitHubPullRequestUrl),
|
|
53
72
|
status: Schema.optionalWith(WorkStatus, { default: () => "open" as const }),
|
|
73
|
+
claim: Schema.optional(ClaimRecord),
|
|
54
74
|
}
|
|
55
75
|
|
|
56
76
|
export const EpicFrontmatter = Schema.Struct({
|
|
@@ -89,6 +109,7 @@ export type WorkbaseRegistry = Schema.Schema.Type<typeof WorkbaseRegistry>
|
|
|
89
109
|
export type Dependency = Schema.Schema.Type<typeof Dependency>
|
|
90
110
|
export type RepositoryReference = Schema.Schema.Type<typeof RepositoryReference>
|
|
91
111
|
export type WorkStatus = Schema.Schema.Type<typeof WorkStatus>
|
|
112
|
+
export type ClaimRecord = Schema.Schema.Type<typeof ClaimRecord>
|
|
92
113
|
export type EpicFrontmatter = Schema.Schema.Type<typeof EpicFrontmatter>
|
|
93
114
|
export type TaskFrontmatter = Schema.Schema.Type<typeof TaskFrontmatter>
|
|
94
115
|
export type PhaseFrontmatter = Schema.Schema.Type<typeof PhaseFrontmatter>
|