@markjaquith/agency 2.13.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.
@@ -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(
@@ -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>